home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / gdevstc.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-01  |  115.0 KB  |  3,554 lines

  1. /* Copyright (C) 1995, 1996 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of AFPL Ghostscript.
  4.   
  5.   AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  6.   distributor accepts any responsibility for the consequences of using it, or
  7.   for whether it serves any particular purpose or works at all, unless he or
  8.   she says so in writing.  Refer to the Aladdin Free Public License (the
  9.   "License") for full details.
  10.   
  11.   Every copy of AFPL Ghostscript must include a copy of the License, normally
  12.   in a plain ASCII text file named PUBLIC.  The License grants you the right
  13.   to copy, modify and redistribute AFPL Ghostscript, but only under certain
  14.   conditions described in the License.  Among other things, the License
  15.   requires that the copyright notice and this notice be preserved on all
  16.   copies.
  17. */
  18.  
  19. /*$Id: gdevstc.c,v 1.2 2000/09/19 19:00:22 lpd Exp $*/
  20. /* Epson Stylus-Color Printer-Driver */
  21.  
  22. /***
  23.  *** This file was "copied" from gdevcdj.c (ghostscript-3.12), which was
  24.  *** contributed by:
  25.  ***    George Cameron      - g.cameron@biomed.abdn.ac.ukis
  26.  ***    Koert Zeilstra      - koert@zen.cais.com
  27.  ***    Eckhard Rueggeberg  - eckhard@ts.go.dlr.de
  28.  ***
  29.  *** Some of the ESC/P2-code was drawn from gdevescp.c, contributed by
  30.  ***    Richard Brown       - rab@eos.ncsu.edu
  31.  ***
  32.  *** The POSIX-Interrupt-Code is from (Compile-Time-Option -DSTC_SIGNAL)
  33.  ***    Frederic Loyer      - loyer@ensta.fr
  34.  ***
  35.  *** And several improvements are based on discussions with
  36.  ***    Brian Converse      - BCONVERSE@ids.net
  37.  ***    Bill Davidson       - bdavidson@ra.isisnet.com
  38.  ***    Gero Guenther       - gero@cs.tu-berlin.de
  39.  ***    Jason Patterson     - jason@reflections.com.au
  40.  ***    ? Rueschstroer      - rue@ibe.med.uni-muenchen.de
  41.  ***    Steven Singer       - S.Singer@ph.surrey.ac.uk
  42.  ***
  43.  *** And the remaining little rest, mainly the bugs, were written by me:
  44.  *** Gunther Hess           - gunther@elmos.de
  45.  ***
  46.  *** P.S.: there is some documentation, see devices.doc
  47.  ***
  48.  *** Revision-History:
  49.  *** 16-DEC-1994  1.1  - initial Version (GS-Dithering & Plain-Write)
  50.      ...
  51.  *** 30-JAN-1995  1.11 - FS-Improvements, u/sWeave, 1/4/24-Bits
  52.  ***  5-MAR-1995  1.12 - L. Peter Deutsch - updated put_params routine
  53.                          (first distributed version with gs3.33)
  54.  *** 26-APR-1995  1.13 - merged Peters fixes with algorithmic changes:
  55.                          Changed 24Bit-Mode, added 32Bit-Mode (moves colors)
  56.                          [Arrgh: much better than 1.12, but patch was lost]
  57.  ***  5-JUN-1995  1.14 - Added Color-Correction & Transfer-Curves
  58.                          (Several Beta-Testers, but not distributed)
  59.      ...
  60.  *** 24-JUL-1995  1.16 - Made dithering-Algorithms external-functions.
  61.                          (Mailed for Beta-Distribution)
  62.  *** 10-AUG-1995  1.17 - Several Bug-Fixes and some new features:
  63.                          CMYK10-Coding added
  64.                          Readonly Parameters added
  65.                           "Algorithms", "BitsPerComponent", "Version"
  66.                          Parameters Flag0-4, Model, OutputCode
  67.                          (mailed for distribution)
  68.  *** 14-SEP-1995  1.18   Fixes Bugs with Borland C (gs3.47)
  69.  *** 23-SEP-1995  1.19 - reorganized printcode + bug-fixing
  70.  *** 24-SEP-1995  1.20 - Little Cleanup for the release
  71.  *** 25-SEP-1995  1.21 - Readonly-Parameters added to put_params.
  72.  *** 31-Dec-1995  1.22 - Sanitary Engineering on the code
  73.  *** 16-Jan-1996  1.23 - Added String escp_Release
  74.  ***  8-May-1996  1.90 - Reintroduced Deltarow & Fixed MEMORY-BUG!
  75.  ***/
  76.  
  77. #include "gdevstc.h"
  78. #ifdef    STC_SIGNAL
  79. #  include <signal.h>
  80. #endif /* STC_SIGNAL */
  81. /***
  82.  *** Mode-Table - the various algorithms
  83.  *** (The intention is, that this source can live alone)
  84.  ***/
  85.  
  86. private stc_proc_dither(stc_gscmyk);   /* resides in this file */
  87. private stc_proc_dither(stc_hscmyk);   /* resides in this file */
  88.  
  89. #include <stdlib.h> /* for rand, used in stc_hscmyk */
  90.  
  91. private const stc_dither_t stc_dither[] = {
  92.   {"gscmyk", stc_gscmyk, DeviceCMYK|STC_BYTE|STC_DIRECT,0,{0.0,1.0}},
  93.   {"hscmyk", stc_hscmyk,
  94.   DeviceCMYK|STC_LONG|STC_CMYK10|STC_DIRECT|1*STC_SCAN,1+2*4,
  95.                                                   {0.0,    1023.0}},
  96.   STC_MODI
  97.   { NULL   , NULL      , 0,                  0,{0.0,0.0}}
  98. };
  99.  
  100. /***
  101.  ***  forward-declarations of routines
  102.  ***/
  103.  
  104. /* Primary Device functions
  105.  * (I've the idea to rename the driver to stc)
  106.  */
  107. private dev_proc_print_page(stc_print_page);
  108. private dev_proc_open_device(stc_open);
  109. private dev_proc_close_device(stc_close);
  110. private dev_proc_get_params(stc_get_params);
  111. private dev_proc_put_params(stc_put_params);
  112.  
  113. /*
  114.  * Color-Mapping-functions.
  115.  */
  116.  
  117. /* routines for monochrome monochrome modi */
  118. private dev_proc_map_rgb_color(stc_map_gray_color);
  119. private dev_proc_map_color_rgb(stc_map_color_gray);
  120.  
  121. /* routines for RGB-Modi */
  122. private dev_proc_map_rgb_color(stc_map_rgb_color);
  123. private dev_proc_map_color_rgb(stc_map_color_rgb);
  124.  
  125. /* routines for general CMYK-Modi */
  126. private dev_proc_map_cmyk_color(stc_map_cmyk_color);
  127. private dev_proc_map_color_rgb(stc_map_color_cmyk);
  128.  
  129. /* routines for 10Bit/Component CMYK */
  130. private dev_proc_map_cmyk_color(stc_map_cmyk10_color);
  131. private dev_proc_map_color_rgb(stc_map_color_cmyk10);
  132.  
  133. /***
  134.  *** Table of Device-Procedures
  135.  ***/
  136. private gx_device_procs stcolor_procs = {
  137.         stc_open,
  138.         gx_default_get_initial_matrix,
  139.         gx_default_sync_output,
  140.         gdev_prn_output_page,
  141.         stc_close,
  142.         NULL,
  143.         stc_map_color_cmyk,
  144.         NULL,   /* fill_rectangle */
  145.         NULL,   /* tile_rectangle */
  146.         NULL,   /* copy_mono */
  147.         NULL,   /* copy_color */
  148.         NULL,   /* draw_line */
  149.         gx_default_get_bits,
  150.         stc_get_params,
  151.         stc_put_params,
  152.         stc_map_cmyk_color
  153. };
  154.  
  155. /***
  156.  *** A local dummy-array for extvals
  157.  ***/
  158.  
  159. private float defext[] = { 0.0, 1.0 };
  160.  
  161. /***
  162.  *** Main device-control structure
  163.  ***/
  164. stcolor_device far_data gs_stcolor_device = {
  165.    prn_device_body(stcolor_device, stcolor_procs, "stcolor",
  166.       DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
  167.       X_DPI,  Y_DPI,
  168.       STC_L_MARGIN,STC_B_MARGIN,STC_R_MARGIN,STC_T_MARGIN,
  169.       4,  4, 1, 1, 2, 2,            /* default: cmyk-direct */
  170.       stc_print_page),
  171.      {STCNWEAVE,                    /* stcflags:  noWeave/bidirectional */
  172.       1,                            /* stcbits:   matches the default */
  173.       stc_dither,                   /* stcdither: first algorithm */
  174.       NULL,                         /* stcam:     NULL -> not used */
  175.       { NULL, NULL, NULL, NULL},    /* extcode:   none defined yet */
  176.       {    0,    0,    0,    0},    /* sizcode:   0, since no extcode yet */
  177.       { NULL, NULL, NULL, NULL},    /* stccode:   computed by put_params */
  178.       {defext,defext,defext,defext},/* extvals:   default */
  179.       {    2,    2,    2,    2},    /* sizvals:   default countof(defext) */
  180.       { NULL, NULL, NULL, NULL},    /* stcvals:   computed by put_params */
  181.       {    0,    0,    0},          /* white-run */
  182.       {    0,    0,    0},          /* white-end */
  183.       {NULL,0,false},               /* algorithm-table */
  184.       {NULL,0,false},               /* initialization-String (BOP) */
  185.       {NULL,0,false},               /* release-String (EOP) */
  186.       0,0,0,0,                      /* New escp-stuff */
  187.       1}                            /* itemsize used by algorithm */
  188. };
  189. /***
  190.  *** Test for white scan-lines
  191.  ***/
  192. private bool stc_iswhite(P3(stcolor_device *, int, byte *));
  193.  
  194. /***
  195.  *** Functions used for conversion inside the print-loop
  196.  ***/
  197. #define stc_proc_iconvert(Name) \
  198. byte * Name(P4(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line))
  199.  
  200. private stc_proc_iconvert(stc_any_depth);    /* general input-conversion */
  201. private stc_proc_iconvert(stc_rgb24_long);   /* 24Bit RGB  -> long's */
  202.  
  203. private stc_proc_iconvert(stc_cmyk32_long);  /* 32Bit CMYK -> long's */
  204. private stc_proc_iconvert(stc_any_direct);   /* use ext_data as input */
  205.  
  206. private stc_proc_iconvert(stc_cmyk10_byte);  /* CMYK10->vals-> any type */
  207. private stc_proc_iconvert(stc_cmyk10_long);  /* CMYK10->vals-> any type */
  208. private stc_proc_iconvert(stc_cmyk10_float); /* CMYK10->vals-> any type */
  209. private stc_proc_iconvert(stc_cmyk10_dbyte); /* CMYK10 direct bytes */
  210. private stc_proc_iconvert(stc_cmyk10_dlong); /* CMYK10 direct longs */
  211.  
  212. /***
  213.  *** Print-functions
  214.  ***/
  215. private void stc_print_weave(P2(stcolor_device *sd,FILE *prn_stream));
  216. private void stc_print_bands(P2(stcolor_device *sd,FILE *prn_stream));
  217. private void stc_print_delta(P2(stcolor_device *sd,FILE *prn_stream));
  218. private int  stc_print_setup(P1(stcolor_device *sd));
  219.  
  220. /***
  221.  *** compute the ESC/P2 specific values
  222.  ***/
  223.  
  224. private int 
  225. stc_print_setup(stcolor_device *sd) 
  226. {
  227.  
  228. /*
  229.  * Compute the resolution-parameters
  230.  */
  231.    sd->stc.escp_u = 3600.0 / sd->y_pixels_per_inch; /* y-units */
  232.    sd->stc.escp_h = 3600.0 / sd->x_pixels_per_inch; /* x-units */
  233.    sd->stc.escp_v = sd->stc.flags & (STCUWEAVE | STCNWEAVE) ?
  234.                     sd->stc.escp_u : 40;
  235. /*
  236.  * Initialize color
  237.  */
  238.    sd->stc.escp_c = 0; /* preselect-black */
  239.  
  240. /*
  241.  * Band-Width
  242.  */
  243.    if((sd->stc.flags & STCBAND) == 0) {
  244.       if(sd->stc.escp_v != sd->stc.escp_u)            sd->stc.escp_m = 15;
  245.       else if(STCSTCII == (sd->stc.flags & STCMODEL)) sd->stc.escp_m =  1;
  246.       else if(  sd->stc.flags & STCUWEAVE)            sd->stc.escp_m =  1;
  247.       else if((sd->stc.escp_v == sd->stc.escp_u) &&
  248.               (sd->stc.escp_u == 5))                  sd->stc.escp_m =  1;
  249.       else                                            sd->stc.escp_m =  1;
  250.    }
  251.  
  252. /*
  253.  * Page-Dimensions
  254.  */
  255.    if((sd->stc.flags & STCWIDTH ) == 0)
  256.        sd->stc.escp_width = sd->width -
  257.            (dev_l_margin(sd)+dev_r_margin(sd))*sd->x_pixels_per_inch;
  258.  
  259.    if((sd->stc.flags & STCHEIGHT) == 0)
  260.        sd->stc.escp_height = sd->height;
  261.  
  262.    if((sd->stc.flags & STCTOP) == 0)
  263.        sd->stc.escp_top = dev_t_margin(sd)*sd->y_pixels_per_inch;
  264.  
  265.    if((sd->stc.flags & STCBOTTOM) == 0)
  266.       sd->stc.escp_bottom = sd->height - dev_b_margin(sd)*sd->y_pixels_per_inch;
  267.  
  268.    if((sd->stc.flags & STCINIT) == 0) { /* No Initialization-String defined */
  269.       int need  = 8  /* Reset, Graphics-Mode 1 */
  270.                 + 6  /* MicroWeave */
  271.                 + 6  /* Select Units */
  272.                 + 7  /* Set Page-Length */
  273.                 + 9  /* Set Margins */
  274.                 + 3; /* Select Unidirectionality */
  275.       byte *bp  = (byte *) (sd->stc.escp_init.data);
  276.  
  277.       if(need != sd->stc.escp_init.size) {  /* Reallocate */
  278.  
  279.          if(NULL != (bp = gs_malloc(need,1,"stcolor/init"))) { /* Replace */
  280.             if(0 != sd->stc.escp_init.size)
  281.                gs_free((byte *)sd->stc.escp_init.data,sd->stc.escp_init.size,1,
  282.                        "stcolor/init");
  283.             sd->stc.escp_init.data       = bp;
  284.             sd->stc.escp_init.size       = need;
  285.             sd->stc.escp_init.persistent = false;
  286.          }  else {                                             /* Replace */
  287.              return_error(gs_error_VMerror);
  288.          }
  289.       }
  290.  
  291.       if(need != 39) return_error(gs_error_unregistered);
  292.  
  293.       memcpy(bp,
  294. /*                       1 1 11  1 11  1   1 1  2 22 2  2 22  2 22 3  3 3333  3 33*/
  295. /* 0 1  2 34  5  6 7  8 90 1 23  4 56  7   8 9  0 12 3  4 56  7 89 0  1 2345  6 78*/
  296. "\033@\033(G\001\0\1\033(i\1\0w\033(U\001\000u\033(C\2\000hh\033(c\4\000ttbb\033U",
  297.              need);
  298.  
  299.  
  300.       if((sd->stc.flags & STCUWEAVE) != 0) bp[13] = '\1';
  301.       else                                 bp[13] = '\0';
  302.  
  303.       bp[19] =  sd->stc.escp_u;
  304.  
  305.       bp[25] =  sd->stc.escp_height     & 0xff;
  306.       bp[26] = (sd->stc.escp_height>>8) & 0xff;
  307.  
  308.       bp[32] =  sd->stc.escp_top        & 0xff;
  309.       bp[33] = (sd->stc.escp_top>>8)    & 0xff;
  310.       bp[34] =  sd->stc.escp_bottom     & 0xff;
  311.       bp[35] = (sd->stc.escp_bottom>>8) & 0xff;
  312.  
  313.       if(sd->stc.flags & STCUNIDIR)        bp[38] = 1;
  314.       else                                 bp[38] = 0;
  315.  
  316.    }                                    /* No Initialization-String defined */
  317.  
  318.    if((sd->stc.flags & STCRELEASE) == 0) { /* No Release-String defined */
  319.       int need  = 3;  /* ESC @ \f */
  320.       byte *bp  = (byte *) (sd->stc.escp_release.data);
  321.  
  322.       if(need != sd->stc.escp_release.size) {  /* Reallocate */
  323.  
  324.          if(NULL != (bp = gs_malloc(need,1,"stcolor/release"))) { /* Replace */
  325.             if(0 != sd->stc.escp_release.size)
  326.                gs_free((byte *)sd->stc.escp_release.data,sd->stc.escp_release.size,1,
  327.                        "stcolor/release");
  328.             sd->stc.escp_release.data       = bp;
  329.             sd->stc.escp_release.size       = need;
  330.             sd->stc.escp_release.persistent = false;
  331.          }  else {                                             /* Replace */
  332.              return_error(gs_error_VMerror);
  333.          }
  334.       }
  335.  
  336.       if(need != 3) return_error(gs_error_unregistered);
  337.  
  338.       memcpy(bp,"\033@\f",need);
  339.  
  340.    }                                    /* No Release-String defined */
  341.  
  342.    return 0;
  343. }
  344.  
  345. /***
  346.  *** stc_print_page: here we go to do the nasty work
  347.  ***/
  348.  
  349. private int
  350. stc_print_page(gx_device_printer * pdev, FILE * prn_stream)
  351. {
  352.    stcolor_device *sd    = (stcolor_device *) pdev;
  353.    long            flags = sd == NULL ? 0 : sd->stc.flags;
  354.  
  355.    int  npass;           /* # of print-passes (softweave) */
  356.  
  357.    int    ext_size;      /* size of a ghostscript-scanline */
  358.    byte  *ext_line;      /* dyn: for this scanline */
  359.  
  360.    int    alg_size;      /* size of a scanline for the dithering-algorithm */
  361.    byte  *alg_line;      /* dyn: 1 scanline for the dithering-algorithm */
  362.    int    buf_size;      /* size of the private-buffer for dither-function */
  363.    byte  *buf;           /* dyn: the private buffer */
  364.  
  365.    int    prt_pixels;    /* Number of pixels printed */
  366.    byte  *col_line;      /* A Line with a byte per pixel */
  367.  
  368. #define OK4GO        ((flags &   STCOK4GO)              != 0)
  369. #define SORRY        ( flags &= ~STCOK4GO)
  370.  
  371.    if(0 > (npass = stc_print_setup(sd))) return_error(npass);
  372.  
  373.    npass = sd->stc.escp_v / sd->stc.escp_u;
  374.  
  375. /***
  376.  *** Allocate dynamic memory
  377.  ***/
  378.  
  379.    ext_size   = gdev_prn_raster(sd);
  380.    ext_line   = gs_malloc(ext_size,1,"stc_print_page/ext_line");
  381.    if(ext_line == NULL) SORRY;
  382.  
  383.    prt_pixels        = sd->stc.escp_width;
  384.    sd->stc.prt_size  = (prt_pixels+7)/8;
  385.    prt_pixels        =  sd->stc.prt_size * 8;
  386.  
  387.    sd->stc.prt_scans  = sd->height -
  388.       (dev_t_margin(sd)+dev_b_margin(sd))*sd->y_pixels_per_inch;
  389.  
  390.    col_line   = gs_malloc(prt_pixels,1,"stc_print_page/col_line");
  391.    if(col_line == NULL) SORRY;
  392.  
  393.    alg_size  = prt_pixels;
  394.    alg_size *= sd->color_info.num_components;
  395.  
  396.    if((sd->stc.dither->flags & STC_DIRECT) ||
  397.       ((sd->stc.bits                 == 8) &&
  398.        (sd->stc.alg_item                     == 1)))  {
  399.       alg_line = NULL;
  400.    } else {
  401.       alg_line = gs_malloc(alg_size,sd->stc.alg_item,"stc_print_page/alg_line");
  402.       if(alg_line == NULL) SORRY;
  403.    }
  404.  
  405.    buf_size = sd->stc.dither->bufadd
  406.             + alg_size*(sd->stc.dither->flags/STC_SCAN);
  407.    if(buf_size > 0) {
  408.       buf    = gs_malloc(buf_size,sd->stc.alg_item,"stc_print_page/buf");
  409.       if(buf == NULL) SORRY;
  410.    } else {
  411.       buf = NULL;
  412.    }
  413.  
  414. /*
  415.  * compute the number of printer-buffers
  416.  */
  417.  
  418.     for(sd->stc.prt_buf   = 16; sd->stc.prt_buf < (sd->stc.escp_m * npass);
  419.         sd->stc.prt_buf <<= 1);
  420.     if(sd->color_info.num_components > 1) sd->stc.prt_buf *= 4;
  421.  
  422.     sd->stc.prt_width = gs_malloc(sd->stc.prt_buf,sizeof(int),
  423.                         "stc_print_page/prt_width");
  424.     if(sd->stc.prt_width == NULL) SORRY;
  425.  
  426.     sd->stc.prt_data  = gs_malloc(sd->stc.prt_buf,sizeof(byte *),
  427.                         "stc_print_page/prt_data");
  428.  
  429.     if(sd->stc.prt_data == NULL) {
  430.        SORRY;
  431.     } else {
  432.        int i;
  433.  
  434.        for(i = 0; i < sd->stc.prt_buf; ++i) {
  435.           sd->stc.prt_data[i] = gs_malloc(sd->stc.prt_size,1,
  436.                                 "stc_print_page/prt");
  437.           if(sd->stc.prt_data[i] == NULL) SORRY;
  438.        }
  439.     }
  440.  
  441.     sd->stc.seed_size = (sd->stc.prt_size + 2*sizeof(int) - 1)/sizeof(int);
  442.     {
  443.        int i;
  444.        for(i = 0; i < sd->color_info.num_components; ++i) {
  445.           if((flags & STCCOMP) == STCDELTA) {
  446.              sd->stc.seed_row[i] = gs_malloc(sd->stc.seed_size,sizeof(int),
  447.                                    "stc_print_page/seed_row");
  448.              if(sd->stc.seed_row[i] == NULL) SORRY;
  449.              else memset(sd->stc.seed_row[i],0,sd->stc.seed_size*sizeof(int));
  450.           } else {
  451.              sd->stc.seed_row[i] = NULL;
  452.           }
  453.        }
  454.        while(i < countof(sd->stc.seed_row)) sd->stc.seed_row[i++] = NULL;
  455.     }
  456.  
  457.     switch(flags & STCCOMP) {
  458.        case STCPLAIN:
  459.           sd->stc.escp_size = 64 + sd->stc.prt_size;
  460.           break;
  461.        case STCDELTA:
  462.           sd->stc.escp_size = 64 + 2 * sd->stc.prt_size;
  463.           break;
  464.        default:
  465.           sd->stc.escp_size = 64 +
  466.                               sd->stc.prt_size + (sd->stc.prt_size + 127)/128;
  467.           break;
  468.     }
  469.  
  470.     sd->stc.escp_data = gs_malloc(sd->stc.escp_size,1,
  471.                                   "stc_print_page/escp_data");
  472.     if(sd->stc.escp_data == NULL) SORRY;
  473.  
  474. /*
  475.  * If we're still ok, we can print something
  476.  */
  477.  
  478.    if(OK4GO) {
  479.  
  480.       int ncolor;
  481.       int buf_i;
  482.       stc_proc_iconvert((*iconvert)) = stc_any_depth;
  483.  
  484. /*
  485.  * initialize col_line
  486.  */
  487.       if(sd->color_info.num_components == 3) {
  488.          memset(col_line,RED|GREEN|BLUE,prt_pixels);
  489.       } else {
  490.          memset(col_line,0,             prt_pixels);
  491.       }
  492.  
  493. /*
  494.  * select proper conversion for input to algorithm
  495.  */
  496.       if(     (sd->stc.dither->flags & STC_DIRECT ) ||
  497.               ((sd->stc.bits                 == 8) &&
  498.                (sd->stc.alg_item                     == 1)))
  499.          iconvert = stc_any_direct;
  500.       else if((sd->color_info.num_components ==  3) &&
  501.               (sd->color_info.depth          == 24) &&
  502.               (sizeof(long)                  == sd->stc.alg_item))
  503.          iconvert = stc_rgb24_long;
  504.       else if(sd->stc.flags & STCCMYK10) {
  505.          if(     ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE) &&
  506.                  ( sd->stc.dither->minmax[0]         ==    0.0  ))
  507.             iconvert = stc_cmyk10_dbyte;
  508.          else if ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)
  509.             iconvert = stc_cmyk10_byte;
  510.          else if(((sd->stc.dither->flags & STC_TYPE) == STC_LONG) &&
  511.                  ( sd->stc.dither->minmax[0]         ==    0.0  ) &&
  512.                  ( sd->stc.dither->minmax[1]         <= 1023.0  ))
  513.             iconvert = stc_cmyk10_dlong;
  514.          else if( (sd->stc.dither->flags & STC_TYPE) == STC_LONG)
  515.             iconvert = stc_cmyk10_long;
  516.          else
  517.             iconvert = stc_cmyk10_float;
  518.       }
  519.       else if((sd->color_info.num_components ==  4) &&
  520.               (sd->color_info.depth          == 32) &&
  521.               (sizeof(long)                  == sd->stc.alg_item))
  522.          iconvert = stc_cmyk32_long;
  523.  
  524. /*
  525.  * initialize the algorithm
  526.  */
  527.  
  528.       if((*sd->stc.dither->fun)(sd,-prt_pixels,alg_line,buf,col_line) < 0)
  529.          SORRY;
  530.  
  531. /*
  532.  * Main-Print-Loop
  533.  */
  534.  
  535.       if(OK4GO) {
  536. #ifdef    STC_SIGNAL
  537.          sigset_t stc_int_mask, stc_int_save, stc_int_pending;
  538.  
  539.          sigemptyset(&stc_int_mask);
  540.          sigaddset(&stc_int_mask,SIGINT);
  541.          sigprocmask(SIG_BLOCK,&stc_int_mask, &stc_int_save);
  542. #endif /* STC_SIGNAL */
  543.  
  544.  
  545.          if(sd->color_info.num_components > 1) ncolor = 4;
  546.          else                                  ncolor = 1;
  547.  
  548. /*
  549.  * Decide, wether we Adjust Linefeeds or not. (I hate it here)
  550.  */
  551.          if((0   == ((sd->stc.escp_m*sd->stc.escp_u) % 10)) &&
  552.             (256  > ((sd->stc.escp_m*sd->stc.escp_u) / 10))) sd->stc.escp_lf = sd->stc.escp_m;
  553.          else                                                sd->stc.escp_lf = 0;
  554.  
  555. /*
  556.  * prepare run-values, then loop over scans
  557.  */
  558.          sd->stc.stc_y      =  0; /* current printer y-Position */
  559.          sd->stc.buf_y      =  0; /* Top-Position within the buffer */
  560.          sd->stc.prt_y      =  0; /* physical position of the printer */
  561.          buf_i              =  0; /* next free line in buffer */
  562.          sd->stc.flags     &= ~STCPRINT; /* no data yet */
  563.  
  564.          while(sd->stc.stc_y < sd->stc.prt_scans) {  /* Until all scans are processed */
  565.             int need;
  566.  
  567.             need = sd->stc.stc_y + npass * sd->stc.escp_m;
  568.  
  569.             if(sd->stc.buf_y < need) { /* Nr. 5 (give me input) */
  570.  
  571. /* read as much as the buffer can hold */
  572.                if(ncolor == 1) need = sd->stc.stc_y +  sd->stc.prt_buf;
  573.                else            need = sd->stc.stc_y + (sd->stc.prt_buf>>2);
  574.  
  575.                for(;sd->stc.buf_y < need;
  576.                     buf_i = (sd->stc.prt_buf-1) & (buf_i+ncolor),
  577.                     ++sd->stc.buf_y) {
  578.  
  579.                   int color;
  580.                   byte *ext_data;
  581.                   byte *alg_data;
  582.  
  583. /* initialize output data 1st -> may take shortcut */
  584.  
  585.                   for(color = 0; color < ncolor; ++color) {
  586.                      memset(sd->stc.prt_data[buf_i+color],0,sd->stc.prt_size);
  587.                      sd->stc.prt_width[buf_i+color] = 0;
  588.                   }
  589.  
  590.  
  591. /* "read data", immediately continue if all is white */
  592.  
  593.                   if(sd->stc.buf_y < sd->stc.prt_scans) {  /* Test for White */
  594.  
  595.                      gdev_prn_get_bits(pdev,sd->stc.buf_y,ext_line,&ext_data);
  596.  
  597.                      color = stc_iswhite(sd,prt_pixels,ext_data) ? ext_size : 0;
  598.  
  599.                   } else {
  600.  
  601.                      color = ext_size;
  602.  
  603.                   }                        /* Test for White */
  604.  
  605.                   if(color >= ext_size) {  /* bypass processing */
  606.  
  607.                      if(sd->stc.dither->flags & STC_WHITE)
  608.                         (*sd->stc.dither->fun)(sd,prt_pixels,NULL,buf,col_line);
  609.                      continue;
  610.  
  611.                   }                        /* bypass processing */
  612.  
  613. /* convert data for the various cases */
  614.  
  615.                   alg_data = (*iconvert)(sd,ext_data,prt_pixels,alg_line);
  616.  
  617.  
  618. /*
  619.  * invoke the dithering-algorithm
  620.  */
  621.  
  622.                   (*sd->stc.dither->fun)(sd,prt_pixels,alg_data,buf,col_line);
  623. /*
  624.  * convert col_line to printer-format (separate colors)
  625.  */
  626.                   switch(sd->color_info.num_components) {
  627.                   case 1: /* Black & White: just merge into 8 Bytes */
  628.                   {
  629.                       byte *bytein,*byteout;
  630.                       int   width;
  631.  
  632.                       bytein  = col_line;
  633.                       byteout = sd->stc.prt_data[buf_i];
  634.  
  635.                       for(width = 1; width <= sd->stc.prt_size; ++width) {
  636.                           byte tmp = 0;
  637.                           byte i;
  638.  
  639.                           for(i = 128; i; i >>= 1) if(*bytein++) tmp  |= i;
  640.  
  641.                           if(tmp != 0) sd->stc.prt_width[buf_i] = width;
  642.  
  643.                           *byteout++ = tmp;
  644.                       }
  645.                   }
  646.                   break;
  647.                   case 3: /* convert rgb into cmyk */
  648.                   {
  649.                       byte *bytein;
  650.                       int   width;
  651.  
  652.                       bytein  = col_line;
  653.  
  654.                       for(width = 0; width < sd->stc.prt_size; ++width) {
  655.                          byte i,tmp,cmyk[4];
  656.  
  657.                          memset(cmyk,0,4);
  658.  
  659.                          for(i = 128; i; i >>= 1) {
  660.                             static const byte rgb2cmyk[] = {
  661.                                BLACK,            /* 0->Black */
  662.                                CYAN | MAGENTA,   /* 1->BLUE  */
  663.                                CYAN | YELLOW,    /* 2->GREEN */
  664.                                CYAN,             /* 3->CYAN  */
  665.                                MAGENTA | YELLOW, /* 4->RED   */
  666.                                MAGENTA,          /* 5->MAGENTA */
  667.                                YELLOW,           /* 6->YELLOW */
  668.                                0};               /* 7->WHITE */
  669.  
  670.                             tmp = rgb2cmyk[(*bytein++) & 7];
  671.  
  672.                             if(tmp & BLACK)   cmyk[3] |= i;
  673.                             if(tmp & YELLOW)  cmyk[2] |= i;
  674.                             if(tmp & MAGENTA) cmyk[1] |= i;
  675.                             if(tmp & CYAN)    cmyk[0] |= i;
  676.                          }
  677.  
  678.                          for(i = 0; i < 4; ++i) {
  679.                             if(cmyk[i] != 0) sd->stc.prt_width[buf_i+i] = width+1;
  680.                             sd->stc.prt_data[buf_i+i][width] = cmyk[i];
  681.                          }
  682.                       }
  683.                   }
  684.                   break;
  685.                   case 4: /* split cmyk */
  686.                   {
  687.                       byte *bytein;
  688.                       int   width;
  689.  
  690.                       bytein  = col_line;
  691.  
  692.                       for(width = 0; width < sd->stc.prt_size; ++width) {
  693.                          byte i,tmp,cmyk[4];
  694.  
  695.                          memset(cmyk,0,4);
  696.  
  697.                          for(i = 128; i; i >>= 1) {
  698.                             tmp = (*bytein++) & 15;
  699.                             if(tmp & BLACK)   cmyk[3] |= i;
  700.                             if(tmp & YELLOW)  cmyk[2] |= i;
  701.                             if(tmp & MAGENTA) cmyk[1] |= i;
  702.                             if(tmp & CYAN)    cmyk[0] |= i;
  703.                          }
  704.  
  705.                          for(i = 0; i < 4; ++i) {
  706.                             if(cmyk[i] != 0) sd->stc.prt_width[buf_i+i] = width+1;
  707.                             sd->stc.prt_data[buf_i+i][width] = cmyk[i];
  708.                          }
  709.                       }
  710.                   }
  711.                   break;
  712.                   default: break;
  713.                   }
  714.                }
  715.             }                  /* Nr. 5 (give me input) */
  716.  
  717. /*
  718.  *    Nr. 5 has got enough input, now we should print it
  719.  */
  720.             if((flags & STCCOMP) == STCDELTA) stc_print_delta(sd,prn_stream);
  721.             else if(npass > 1)                stc_print_weave(sd,prn_stream);
  722.             else                              stc_print_bands(sd,prn_stream);
  723.  
  724. #ifdef    STC_SIGNAL
  725.             sigpending(&stc_int_pending);
  726.             if(sigismember(&stc_int_pending,SIGINT)) {
  727.                fputs("\033@[Aborted]\f", prn_stream);
  728.                fflush(prn_stream);
  729.                sigprocmask(SIG_SETMASK,&stc_int_save,NULL);
  730.                break;
  731.             }
  732. #endif /* STC_SIGNAL */
  733.  
  734.          }                           /* Until all scans are processed */
  735.  
  736.          if(sd->stc.flags & STCPRINT) {
  737.             if((flags & STCCOMP) == STCDELTA) fputc(0xe3,prn_stream);
  738.             fwrite(sd->stc.escp_release.data,1,sd->stc.escp_release.size,prn_stream);
  739.             fflush(prn_stream);
  740.          }
  741. #ifdef    STC_SIGNAL
  742.          sigprocmask(SIG_SETMASK,&stc_int_save,NULL);
  743. #endif /* STC_DIGNAL */
  744.   
  745.       }
  746.    }
  747.  
  748. /***
  749.  *** Release the dynamic memory
  750.  ***/
  751.  
  752.    if(ext_line != NULL)
  753.       gs_free(ext_line,ext_size,1,"stc_print_page/ext_line");
  754.  
  755.    if(col_line != NULL)
  756.       gs_free(col_line,prt_pixels,1,"stc_print_page/col_line");
  757.  
  758.    if(alg_line != NULL)
  759.       gs_free(alg_line,alg_size,sd->stc.alg_item,
  760.          "stc_print_page/alg_line");
  761.  
  762.    if(buf != NULL)
  763.       gs_free(buf,buf_size,sd->stc.alg_item,"stc_print_page/buf");
  764.  
  765.     if(sd->stc.prt_width != NULL)
  766.        gs_free(sd->stc.prt_width,sd->stc.prt_buf,sizeof(int),
  767.        "stc_print_page/prt_width");
  768.  
  769.     if(sd->stc.prt_data != NULL) {
  770.        int i;
  771.  
  772.        for(i = 0; i < sd->stc.prt_buf; ++i) {
  773.           if(sd->stc.prt_data[i] != NULL)
  774.              gs_free(sd->stc.prt_data[i],sd->stc.prt_size,1,
  775.              "stc_print_page/prt");
  776.        }
  777.  
  778.        gs_free(sd->stc.prt_data,sd->stc.prt_buf,sizeof(byte *),
  779.        "stc_print_page/prt_data");
  780.     }
  781.  
  782.     {
  783.        int i;
  784.        for(i = 0; i < sd->color_info.num_components; ++i) {
  785.           if(sd->stc.seed_row[i] != NULL)
  786.             gs_free(sd->stc.seed_row[i],sd->stc.seed_size,sizeof(int),
  787.             "stc_print_page/seed_row");
  788.        }
  789.     }
  790.  
  791.     if(sd->stc.escp_data != NULL)
  792.        gs_free(sd->stc.escp_data,sd->stc.escp_size,1,
  793.        "stc_print_page/escp_data");
  794.  
  795.    return OK4GO ? 0 : gs_error_undefined;
  796. }
  797.  
  798. /*
  799.  * white-check
  800.  */
  801. private bool 
  802. stc_iswhite(stcolor_device *sd, int prt_pixels,byte *ext_data)
  803. {
  804.    long  b2do = (prt_pixels*sd->color_info.depth+7)>>3;
  805.    int   bcmp = 4 * countof(sd->stc.white_run);
  806.    byte *wht  = (byte *) sd->stc.white_run;
  807.  
  808.    while(b2do >= bcmp) {
  809.       if(memcmp(ext_data,wht,bcmp)) break;
  810.       ext_data += bcmp;
  811.       b2do     -= bcmp;
  812.    }
  813.  
  814.    if((b2do > 0) && (b2do < bcmp))
  815.       b2do  = memcmp(ext_data,sd->stc.white_end,b2do);
  816.  
  817.    return b2do ? false : true;
  818. }
  819.  
  820. /***
  821.  *** A bunch of routines that convert gslines into algorithms format.
  822.  ***/
  823. private byte *
  824. stc_any_depth(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
  825. { /* general conversion */
  826.  
  827.    int p,c,       niext,         nbits;
  828.    gx_color_index ciext,ci,cimsk,cvmsk;
  829.    byte          *ap = alg_line;
  830.  
  831.    nbits =  sd->stc.bits;
  832.    cvmsk = ((gx_color_index) 1<<nbits) - 1;
  833.  
  834. /* it is nonsense to use this algorithm for this cases, but if it claims
  835.  * generality, it should deliver correct results in this cases too */
  836.    if(sd->color_info.depth == (sd->color_info.num_components<<3)) nbits = 8;
  837.  
  838.    cimsk = cvmsk;
  839.    for(c = 1; c < sd->color_info.num_components; ++c)
  840.        cimsk = (cimsk<<nbits) | cvmsk;
  841.  
  842.    ciext = 0;
  843.    niext = 0;
  844.  
  845.    for(p = 0; p < prt_pixels; ++p) { /* over pixels */
  846.  
  847.       ci = ciext;
  848.       for(c =  sd->color_info.depth-niext; c >= 8; c -= 8)
  849.          ci  = (ci<<8) | *ext_data++;
  850.  
  851.       if(c > 0) {         /* partial byte required */
  852.  
  853.          niext  = 8 - c;
  854.          ciext  = *ext_data++;
  855.          ci     = (ci<<c) | (ciext>>niext);
  856.          ciext &= (1L<<niext)-1;
  857.  
  858.       } else if(c < 0) { /* some bits left in ciext */
  859.  
  860.          niext  = -c;
  861.          ciext &= (1L<<niext)-1;
  862.          ci     = ci>>niext;
  863.  
  864.       } else {           /* entire ciext used */
  865.  
  866.          niext = 0;
  867.          ciext = 0;
  868.  
  869.       }                  /* ciext-adjust */
  870.  
  871.       ci &= cimsk;
  872.  
  873. #     define stc_storeapc(T) \
  874.          ((T *)ap)[c] = ((T *)(sd->stc.vals[c]))[ci & cvmsk];
  875.  
  876.       for(c = sd->color_info.num_components; c--;) { /* comp */
  877.          STC_TYPESWITCH(sd->stc.dither,stc_storeapc)
  878.          ci >>= nbits;
  879.       }                                              /* comp */
  880.  
  881. #     undef  stc_storeapc
  882.  
  883.       ap += sd->color_info.num_components * sd->stc.alg_item;
  884.  
  885.    }                                 /* over pixels */
  886.  
  887.    return alg_line;
  888. } /* general conversion */
  889.  
  890. /*
  891.  * rgb-data with depth=24, can use a faster algorithm
  892.  */
  893. private byte *
  894. stc_rgb24_long(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
  895. { /* convert 3 bytes into appropriate long-Values */
  896.   register int   p;
  897.   register long *out   = (long *) alg_line;
  898.   register long *rvals = (long *) (sd->stc.vals[0]);
  899.   register long *gvals = (long *) (sd->stc.vals[1]);
  900.   register long *bvals = (long *) (sd->stc.vals[2]);
  901.  
  902.   for(p = prt_pixels; p; --p) {
  903.      *out++ = rvals[*ext_data++];
  904.      *out++ = gvals[*ext_data++];
  905.      *out++ = bvals[*ext_data++];
  906.   }
  907.  
  908.   return alg_line;
  909. } /* convert 3 bytes into appropriate long-Values */
  910.  
  911. /*
  912.  * cmyk-data with depth=32, can use a faster algorithm
  913.  */
  914. private byte *
  915. stc_cmyk32_long(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
  916. { /* convert 4 bytes into appropriate long-Values */
  917.   register int   p;
  918.   register long *out   = (long *) alg_line;
  919.   register long *cvals = (long *) (sd->stc.vals[0]);
  920.   register long *mvals = (long *) (sd->stc.vals[1]);
  921.   register long *yvals = (long *) (sd->stc.vals[2]);
  922.   register long *kvals = (long *) (sd->stc.vals[3]);
  923.  
  924.   for(p = prt_pixels; p; --p) {
  925.      *out++ = cvals[*ext_data++];
  926.      *out++ = mvals[*ext_data++];
  927.      *out++ = yvals[*ext_data++];
  928.      *out++ = kvals[*ext_data++];
  929.   }
  930.  
  931.   return alg_line;
  932. } /* convert 4 bytes into appropriate long-Values */
  933.  
  934. /*
  935.  * handle indirect encoded cmyk-data
  936.  */
  937. #define STC_CMYK10_ANY(T)\
  938.                                                                             \
  939.       register int p               = prt_pixels;                            \
  940.       register stc_pixel      ci,k,n,mode;                                  \
  941.       register stc_pixel      *in  = (stc_pixel *) ext_data;                \
  942.       register T              *out = (T *) alg_line;                        \
  943.       register T              *cv  = (T *) sd->stc.vals[0];                 \
  944.       register T              *mv  = (T *) sd->stc.vals[1];                 \
  945.       register T              *yv  = (T *) sd->stc.vals[2];                 \
  946.       register T              *kv  = (T *) sd->stc.vals[3];                 \
  947.                                                                             \
  948.       while(p--) {                                                          \
  949.          ci   = *in++;                                                      \
  950.          mode = ci & 3;                                                     \
  951.          k    = (ci>>2) & 0x3ff;                                            \
  952.          if(mode == 3) {                                                    \
  953.             *out++ = cv[0];                                                 \
  954.             *out++ = mv[0];                                                 \
  955.             *out++ = yv[0];                                                 \
  956.             *out++ = kv[k];                                                 \
  957.          } else {                                                           \
  958.             out[3] = kv[k];                                                 \
  959.             n = (ci>>12) & 0x3ff;                                           \
  960.             if(mode == 2) { out[2] = yv[k]; }                               \
  961.             else          { out[2] = yv[n]; n = (ci>>22) & 0x3ff; }         \
  962.             if(mode == 1) { out[1] = mv[k]; }                               \
  963.             else          { out[1] = mv[n]; n = (ci>>22) & 0x3ff; }         \
  964.             if(mode == 0)   out[0] = cv[k];                                 \
  965.             else            out[0] = cv[n];                                 \
  966.             out += 4;                                                       \
  967.          }                                                                  \
  968.       }                                                                     \
  969.                                                                             \
  970.       return alg_line;
  971.  
  972. private byte *
  973. stc_cmyk10_byte(stcolor_device *sd,
  974.                 byte *ext_data,int prt_pixels,byte *alg_line)
  975. {
  976.    STC_CMYK10_ANY(byte)
  977. }
  978. private byte *
  979. stc_cmyk10_long(stcolor_device *sd,
  980.                 byte *ext_data,int prt_pixels,byte *alg_line)
  981. {
  982.    STC_CMYK10_ANY(long)
  983. }
  984. private byte *
  985. stc_cmyk10_float(stcolor_device *sd,
  986.                 byte *ext_data,int prt_pixels,byte *alg_line)
  987. {
  988.    STC_CMYK10_ANY(float)
  989. }
  990.  
  991. #undef  STC_CMYK10_ANY
  992.  
  993. #define STC_CMYK10_DANY(T)\
  994.                                                                             \
  995.       register int p               = prt_pixels;                            \
  996.       register stc_pixel       ci,k,n,mode;                                 \
  997.       register stc_pixel      *in  = (stc_pixel *) ext_data;                \
  998.       register T              *out = (T *) alg_line;                        \
  999.                                                                             \
  1000.       while(p--) {                                                          \
  1001.          ci   = *in++;                                                      \
  1002.          mode = ci & 3;                                                     \
  1003.          k    = (ci>>2) & 0x3ff;                                            \
  1004.          if(mode == 3) {                                                    \
  1005.             *out++ = 0;                                                     \
  1006.             *out++ = 0;                                                     \
  1007.             *out++ = 0;                                                     \
  1008.             *out++ = k;                                                     \
  1009.          } else {                                                           \
  1010.             out[3] = k;                                                     \
  1011.             n = (ci>>12) & 0x3ff;                                           \
  1012.             if(mode == 2) { out[2] = k; }                                   \
  1013.             else          { out[2] = n; n = (ci>>22) & 0x3ff; }             \
  1014.             if(mode == 1) { out[1] = k; }                                   \
  1015.             else          { out[1] = n; n = (ci>>22) & 0x3ff; }             \
  1016.             if(mode == 0)   out[0] = k;                                     \
  1017.             else            out[0] = n;                                     \
  1018.             out += 4;                                                       \
  1019.          }                                                                  \
  1020.       }                                                                     \
  1021.                                                                             \
  1022.       return alg_line;
  1023.  
  1024.  
  1025. private byte *
  1026. stc_cmyk10_dbyte(stcolor_device *sd,
  1027.                 byte *ext_data,int prt_pixels,byte *alg_line)
  1028. {
  1029.    STC_CMYK10_DANY(byte)
  1030. }
  1031. private byte *
  1032. stc_cmyk10_dlong(stcolor_device *sd,
  1033.                 byte *ext_data,int prt_pixels,byte *alg_line)
  1034. {
  1035.    STC_CMYK10_DANY(long)
  1036. }
  1037.  
  1038. #undef  STC_CMYK10_DANY
  1039.  
  1040. /*
  1041.  * if the algorithm uses bytes & bytes are in ext_data, use them
  1042.  */
  1043. /*ARGSUSED*/
  1044. private byte *
  1045. stc_any_direct(stcolor_device *sd,byte *ext_data,int prt_pixels,byte *alg_line)
  1046. { /* return ext_data */
  1047.   return ext_data;
  1048. } /* return ext_data */
  1049.  
  1050. /* ----------------------------------------------------------------------- */
  1051. /* stc_rle: epson ESC/P2 RLE-Encoding
  1052.  */
  1053. private int 
  1054. stc_rle(byte *out,const byte *in,int width)
  1055. {
  1056.  
  1057.    int used = 0;
  1058.    int crun,cdata;
  1059.    byte run;
  1060.  
  1061.    if(in != NULL) { /* Data present */
  1062.  
  1063.       crun = 1;
  1064.  
  1065.       while(width > 0) { /* something to compress */
  1066.  
  1067.          run = in[0];
  1068.  
  1069.          while((width > crun) && (run == in[crun])) if(++crun == 129) break;
  1070.  
  1071.          if((crun > 2) || (crun == width)) { /* use this run */
  1072.  
  1073.             *out++ = (257 - crun) & 0xff; *out++ = run; used += 2;
  1074.  
  1075.             width -= crun; in    += crun;
  1076.             crun = 1;
  1077.  
  1078.          } else {                            /* ignore this run */
  1079.  
  1080.             for(cdata = crun; (width > cdata) && (crun < 4);) {
  1081.                if(run  == in[cdata]) crun += 1;
  1082.                else run = in[cdata], crun  = 1;
  1083.                if(++cdata == 128) break;
  1084.             }
  1085.  
  1086.             if(crun < 3) crun   = 0;    /* ignore trailing run */
  1087.             else         cdata -= crun;
  1088.  
  1089.             *out++ = cdata-1;     used++;
  1090.             memcpy(out,in,cdata); used += cdata; out   += cdata;
  1091.  
  1092.             width -= cdata; in    += cdata;
  1093.  
  1094.          }              /* use/ignore run */
  1095.  
  1096.       }                  /* something to compress */
  1097.  
  1098.    } else {         /* Empty scans to fill bands */
  1099.  
  1100.       while(width > 0) {
  1101.          crun   = width > 129 ? 129 : width;
  1102.          width -= crun;
  1103.          *out++ = (257 - crun) & 0xff;
  1104.          *out++ = 0;
  1105.          used  += 2;
  1106.       }
  1107.    }                /* Data present or empty */
  1108.    return used;
  1109. }
  1110.  
  1111.  
  1112. /*
  1113.  * Horizontal & vertical positioning, color-selection, "ESC ."
  1114.  */
  1115. private int 
  1116. stc_print_escpcmd(stcolor_device *sd, FILE *prn_stream,
  1117.    int escp_used, int color,int m,int wbytes)
  1118. {
  1119.  
  1120.    int dy  = sd->stc.stc_y - sd->stc.prt_y; /* number of units to skip */
  1121.    int nlf;
  1122.  
  1123. /* ESC-R color codes, used only here */
  1124.    static const byte stc_colors[] = { 0x02, 0x01, 0x04, 0x00 }; /* CMYK */
  1125.  
  1126. /*
  1127.  * initialize the printer, if necessary
  1128.  */
  1129.    if(0 == (sd->stc.flags & STCPRINT)) {
  1130.  
  1131.       fwrite(sd->stc.escp_init.data,1,sd->stc.escp_init.size,prn_stream);
  1132.  
  1133.       if(0 < sd->stc.escp_lf) { /* Adjust Linefeed */
  1134.          fputc('\033',        prn_stream);
  1135.          fputc('+',           prn_stream);
  1136.          fputc(((sd->stc.escp_m*sd->stc.escp_u) / 10),prn_stream);
  1137.       }                         /* Adjust Linefeed */
  1138.       sd->stc.flags |= STCPRINT;
  1139.    }
  1140.  
  1141.    sd->stc.escp_data[escp_used++]  = '\r';     /* leftmost position */
  1142.  
  1143.    if(dy) {                                    /* position the printer */
  1144.       if(( sd->stc.escp_lf      >  0) && /* Linefeed allowed */
  1145.          ((dy % sd->stc.escp_lf) == 0))   /* and possible */
  1146.             nlf = dy / sd->stc.escp_lf;
  1147.       else  nlf = 7;
  1148.          
  1149.       if(nlf > 6) {
  1150.          sd->stc.escp_data[escp_used++]  = '\033';
  1151.          sd->stc.escp_data[escp_used++]  = '(';
  1152.          sd->stc.escp_data[escp_used++]  = 'V';
  1153.          sd->stc.escp_data[escp_used++]  = '\002';
  1154.          sd->stc.escp_data[escp_used++]  = '\000';
  1155.          sd->stc.escp_data[escp_used++]  =  sd->stc.stc_y       & 0xff;
  1156.          sd->stc.escp_data[escp_used++]  = (sd->stc.stc_y >> 8) & 0xff;
  1157.       } else {
  1158.          while(nlf--) sd->stc.escp_data[escp_used++] = '\n';
  1159.       }
  1160.       sd->stc.prt_y = sd->stc.stc_y;
  1161.    }                                           /* position the printer */
  1162.  
  1163.    if((sd->color_info.num_components > 1) &&
  1164.       (sd->stc.escp_c != stc_colors[color])) { /* select color */
  1165.        sd->stc.escp_data[escp_used++]  = '\033';
  1166.        sd->stc.escp_data[escp_used++]  = 'r';
  1167.        sd->stc.escp_c                  = stc_colors[color];
  1168.        sd->stc.escp_data[escp_used++]  = sd->stc.escp_c;
  1169.    }                                           /* select color */
  1170.  
  1171. /*
  1172.  * Build the command used
  1173.  */
  1174.    sd->stc.escp_data[escp_used++] = '\033';
  1175.    sd->stc.escp_data[escp_used++] = '.';
  1176.    sd->stc.escp_data[escp_used++] =
  1177.        (sd->stc.flags & STCCOMP) == STCPLAIN ? 0 : 1;
  1178.    sd->stc.escp_data[escp_used++] = sd->stc.escp_v;
  1179.    sd->stc.escp_data[escp_used++] = sd->stc.escp_h;
  1180.    sd->stc.escp_data[escp_used++] = m;
  1181.    sd->stc.escp_data[escp_used++] = (wbytes<<3) & 0xff; /* width in Pixels */
  1182.    sd->stc.escp_data[escp_used++] = (wbytes>>5) & 0xff;
  1183.  
  1184.    return escp_used;
  1185. }
  1186.  
  1187. /*
  1188.  * compute width of a group of scanlines
  1189.  */
  1190. private int 
  1191. stc_bandwidth(stcolor_device *sd,int color,int m,int npass)
  1192. {
  1193.    int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
  1194.    int buf_a  = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
  1195.    int w      = 0;
  1196.  
  1197.    while(m-- > 0) { /* check width */
  1198.       if(sd->stc.prt_width[buf_a] > w) w = sd->stc.prt_width[buf_a];
  1199.       buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor * npass);
  1200.    }                       /* check width */
  1201.  
  1202.    return w;
  1203. }
  1204.  
  1205. /*
  1206.  * Multi-Pass Printing-Routine
  1207.  */
  1208. private void 
  1209. stc_print_weave(stcolor_device *sd, FILE *prn_stream)
  1210. {
  1211.  
  1212.    int escp_used,nprint,nspace,color,buf_a,iprint,w;
  1213.  
  1214.    int npass  = sd->stc.escp_v / sd->stc.escp_u;
  1215.    int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
  1216.  
  1217.  
  1218.    while(sd->stc.stc_y < sd->stc.prt_scans) {
  1219.  
  1220. /*
  1221.  * compute spacing & used heads (seems to work with odd escp_m)
  1222.  */
  1223.       if(sd->stc.stc_y >= sd->stc.escp_m) { /* in normal mode */
  1224.          nprint = sd->stc.escp_m;
  1225.          nspace = sd->stc.escp_m;
  1226.       } else if((sd->stc.stc_y) < npass) {                /* initialisation */
  1227.          nprint = sd->stc.escp_m - sd->stc.stc_y * ((sd->stc.escp_m+1)/npass);
  1228.          nspace = 1;
  1229.       } else {                                   /* switch to normal */
  1230.          nprint = sd->stc.escp_m - sd->stc.stc_y * ((sd->stc.escp_m+1)/npass);
  1231.          nspace = sd->stc.escp_m - sd->stc.stc_y;
  1232.       }
  1233.       iprint = sd->stc.stc_y + npass * nprint;
  1234.       if(sd->stc.buf_y < iprint) break;
  1235.  
  1236.       escp_used = 0;
  1237.       for(color = 0; color < ncolor; ++color) { /* print the colors */
  1238.  
  1239.          if(0 == (w = stc_bandwidth(sd,color,nprint,npass))) continue;
  1240.  
  1241.          escp_used = stc_print_escpcmd(sd,prn_stream,
  1242.                                        escp_used,color,sd->stc.escp_m,w);
  1243.  
  1244.          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
  1245.          for(iprint = 0; iprint < nprint; ++iprint) { /* send data */
  1246.  
  1247.             if((sd->stc.flags & STCCOMP) == STCPLAIN) {
  1248.                memcpy(sd->stc.escp_data+escp_used,sd->stc.prt_data[buf_a],w);
  1249.                escp_used += w;
  1250.             } else {
  1251.                escp_used += stc_rle(sd->stc.escp_data+escp_used,
  1252.                                     sd->stc.prt_data[buf_a],w);
  1253.             }
  1254.  
  1255.             fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
  1256.             escp_used = 0;
  1257.  
  1258.             buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor * npass);
  1259.  
  1260.          }                                            /* send data */
  1261.  
  1262.          while(iprint++ < sd->stc.escp_m) {  /* add empty rows */
  1263.  
  1264.             if((sd->stc.flags & STCCOMP) == STCPLAIN) {
  1265.                memset(sd->stc.escp_data+escp_used,0,w);
  1266.                escp_used += w;
  1267.             } else {
  1268.                escp_used += stc_rle(sd->stc.escp_data+escp_used,NULL,w);
  1269.             }
  1270.  
  1271.             fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
  1272.             escp_used = 0;
  1273.          }                               /* add empty rows */
  1274.       }                                             /* print the colors */
  1275.  
  1276.       sd->stc.stc_y += nspace;
  1277.    }
  1278. }
  1279.  
  1280. /*
  1281.  * Single-Pass printing-Routine
  1282.  */
  1283. private void 
  1284. stc_print_bands(stcolor_device *sd, FILE *prn_stream)
  1285. {
  1286.  
  1287.    int escp_used,color,buf_a,iprint,w,m;
  1288.  
  1289.    int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
  1290.  
  1291.    while(sd->stc.stc_y < sd->stc.prt_scans) {
  1292.  
  1293. /*
  1294.  * find the begin of the band
  1295.  */
  1296.       for(w = 0; sd->stc.stc_y < sd->stc.buf_y; ++sd->stc.stc_y) {
  1297.          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor);
  1298.          for(color = 0; color < ncolor; ++color)
  1299.             if(sd->stc.prt_width[buf_a+color] > w)
  1300.                w = sd->stc.prt_width[buf_a+color];
  1301.          if(w != 0) break;
  1302.       }
  1303.       if(w == 0) break;
  1304. /*
  1305.  * adjust the band-height
  1306.  */
  1307.       w = sd->stc.prt_scans - sd->stc.stc_y;
  1308.       if((w < sd->stc.escp_m) && (sd->stc.escp_v != 40)) {
  1309.          if(w < 8)       m =  1;
  1310.          else if(w < 24) m =  8;
  1311.          else            m = 24;
  1312.       } else {
  1313.          m = sd->stc.escp_m;
  1314.       }
  1315.  
  1316.       if(sd->stc.buf_y < (sd->stc.stc_y+m)) break;
  1317.  
  1318.       escp_used = 0;
  1319.       for(color = 0; color < ncolor; ++color) { /* print the colors */
  1320.  
  1321.          if(0 == (w = stc_bandwidth(sd,color,m,1))) continue; /* shortcut */
  1322.  
  1323.          escp_used = stc_print_escpcmd(sd,prn_stream,escp_used,color,m,w);
  1324.  
  1325.          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
  1326.          for(iprint = 0; iprint < m; ++iprint) { /* send data */
  1327.  
  1328.             if((sd->stc.flags & STCCOMP) == STCPLAIN) {
  1329.                memcpy(sd->stc.escp_data+escp_used,sd->stc.prt_data[buf_a],w);
  1330.                escp_used += w;
  1331.             } else {
  1332.                escp_used += stc_rle(sd->stc.escp_data+escp_used,
  1333.                                     sd->stc.prt_data[buf_a],w);
  1334.             }
  1335.  
  1336.             fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
  1337.             escp_used = 0;
  1338.  
  1339.             buf_a = (sd->stc.prt_buf-1) & (buf_a + ncolor);
  1340.  
  1341.          }                                            /* send data */
  1342.  
  1343.       }                                             /* print the colors */
  1344.  
  1345.       sd->stc.stc_y += m;
  1346.    }
  1347. }
  1348. /* ----------------------------------------------------------------------- */
  1349.  
  1350. private int 
  1351. stc_deltarow(byte *out,const byte *in,int width,byte *seed)
  1352. {
  1353.  
  1354.    int istop,nmove,ndata,i,j;
  1355.    int *wseed = (int *) seed;
  1356.    int used   = 0;
  1357.  
  1358.    seed += sizeof(int);
  1359.  
  1360.    if((in != NULL) && (width > 0)) { /* Data present */
  1361.  
  1362.       istop = width < wseed[0] ? wseed[0] : width;
  1363.  
  1364.       i = 0;
  1365.       while(i < istop) {
  1366.  
  1367.          for(j = i; j < istop; ++j) if(in[j] != seed[j]) break;
  1368.  
  1369.          nmove = j - i;
  1370.  
  1371.          if(nmove > 0) { /* issue a move */
  1372.            i     = j;
  1373.            if(i == istop) break;
  1374.  
  1375.            if(       nmove <   8) {
  1376.               out[used++] = 0x40 | nmove;
  1377.            } else if(nmove < 128) {
  1378.               out[used++] = 0x51;
  1379.               out[used++] = nmove;
  1380.            } else {
  1381.               out[used++] = 0x52;
  1382.               out[used++] = 0xff & nmove;
  1383.               out[used++] = 0xff & (nmove>>8);
  1384.            }
  1385.          }           /* issue a move */
  1386.  
  1387. /*
  1388.  * find the end of this run
  1389.  */
  1390.          nmove = 0;
  1391.          for(j = i+1; (j < istop) && ((nmove < 4)); ++j) {
  1392.             if(in[j] == seed[j]) nmove += 1;
  1393.             else                 nmove  = 0;
  1394.          }
  1395.  
  1396.          ndata = j-i-nmove;
  1397.  
  1398.          nmove = stc_rle(out+used+3,in+i,ndata);
  1399.          if(nmove < 16) {
  1400.             out[used++] = 0x20 | nmove;
  1401.             for(j = 0; j < nmove; ++j) out[used+j] = out[used+j+2];
  1402.          } else if(nmove < 256) {
  1403.             out[used++] = 0x31;
  1404.             out[used++] = nmove;
  1405.             for(j = 0; j < nmove; ++j) out[used+j] = out[used+j+1];
  1406.          } else {
  1407.             out[used++] = 0x32;
  1408.             out[used++] = 0xff & nmove;
  1409.             out[used++] = 0xff & (nmove>>8);
  1410.          }
  1411.          used += nmove;
  1412.          i    += ndata;
  1413.       }
  1414.  
  1415.       memcpy(seed,in,istop);
  1416.       wseed[0] = width;
  1417.  
  1418.    } else if(wseed[0] > 0) { /* blank line, but seed has data */
  1419.  
  1420.       out[used++] = 0xe1; /* clear row */
  1421.       memset(seed,0,wseed[0]);
  1422.       wseed[0] = 0;
  1423.  
  1424.    }
  1425.  
  1426.    return used;
  1427. }
  1428.  
  1429. /*
  1430.  * Slightly different single-pass printing
  1431.  */
  1432. private void
  1433. stc_print_delta(stcolor_device *sd, FILE *prn_stream)
  1434. {
  1435.  
  1436.    int color,buf_a,w;
  1437.    int escp_used = 0; 
  1438.    int ncolor = sd->color_info.num_components == 1 ? 1 : 4;
  1439.  
  1440.    while(sd->stc.stc_y < sd->stc.prt_scans) {
  1441.  
  1442. /*
  1443.  * find the begin of the band
  1444.  */
  1445.       for(w = 0; sd->stc.stc_y < sd->stc.buf_y; ++sd->stc.stc_y) {
  1446.          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor);
  1447.          for(color = 0; color < ncolor; ++color)
  1448.             if(sd->stc.prt_width[buf_a+color] > w)
  1449.                w = sd->stc.prt_width[buf_a+color];
  1450.          if(w != 0) break;
  1451.       }
  1452.  
  1453.       if(sd->stc.buf_y == sd->stc.stc_y) break;
  1454.  
  1455.       escp_used = 0;
  1456.  
  1457. /*
  1458.  * Send Initialization & ESC . 3 once
  1459.  */
  1460.       if(0 == (sd->stc.flags & STCPRINT)) {
  1461.  
  1462.          sd->stc.flags |= STCPRINT;
  1463.  
  1464.          fwrite(sd->stc.escp_init.data,1,sd->stc.escp_init.size,prn_stream);
  1465.  
  1466.          sd->stc.escp_data[escp_used++] = '\033';
  1467.          sd->stc.escp_data[escp_used++] = '.';
  1468.          sd->stc.escp_data[escp_used++] =  3;
  1469.          sd->stc.escp_data[escp_used++] = sd->stc.escp_v;
  1470.          sd->stc.escp_data[escp_used++] = sd->stc.escp_h;
  1471.          sd->stc.escp_data[escp_used++] = sd->stc.escp_m;
  1472.          sd->stc.escp_data[escp_used++] = 0;
  1473.          sd->stc.escp_data[escp_used++] = 0;
  1474.          sd->stc.escp_data[escp_used++] = 0xe4; /* MOVXBYTE */
  1475.       }
  1476.  
  1477.       if(sd->stc.stc_y != sd->stc.prt_y) { /* really position the printer */
  1478.          w = sd->stc.stc_y - sd->stc.prt_y;
  1479.          if(       w <  16) {
  1480.             sd->stc.escp_data[escp_used++] = 0x60 | w;
  1481.          } else if(w < 256) {
  1482.             sd->stc.escp_data[escp_used++] = 0x71;
  1483.             sd->stc.escp_data[escp_used++] = w;
  1484.          } else {
  1485.             sd->stc.escp_data[escp_used++] = 0x72;
  1486.             sd->stc.escp_data[escp_used++] = 0xff & w;
  1487.             sd->stc.escp_data[escp_used++] = 0xff & (w>>8);
  1488.          }
  1489.          sd->stc.prt_y = sd->stc.stc_y;
  1490.       }                                    /* really position the printer */
  1491.  
  1492.       for(color = 0; color < ncolor; ++color) { /* print the colors */
  1493.  
  1494. /* Color-Selection */
  1495.          if(color == (ncolor-1)) {
  1496.             sd->stc.escp_data[escp_used++] = 0x80; /* Black */
  1497.          } else {
  1498.             switch(color) {
  1499.             case 1:  sd->stc.escp_data[escp_used++] = 0x81; break; /* M */
  1500.             case 2:  sd->stc.escp_data[escp_used++] = 0x84; break; /* Y */
  1501.             default: sd->stc.escp_data[escp_used++] = 0x82; break; /* C */
  1502.             }
  1503.          }
  1504.  
  1505. /* Data-Transfer */
  1506.          buf_a = (sd->stc.prt_buf-1) & (sd->stc.stc_y * ncolor + color);
  1507.  
  1508.          w = stc_deltarow(sd->stc.escp_data+escp_used,
  1509.              sd->stc.prt_data[buf_a],sd->stc.prt_width[buf_a],
  1510.              sd->stc.seed_row[color]);
  1511.  
  1512.          if(w == 0) escp_used -= 1;
  1513.          else       escp_used += w;
  1514.  
  1515.          if(escp_used > 0) fwrite(sd->stc.escp_data,1,escp_used,prn_stream);
  1516.          escp_used = 0;
  1517.  
  1518.       }                                             /* print the colors */
  1519.  
  1520.       sd->stc.stc_y += 1;
  1521.  
  1522.    }
  1523.  
  1524. }
  1525.  
  1526. /* ----------------------------------------------------------------------- */
  1527.  
  1528. /***
  1529.  *** Free-Data: release the specific-Arrays
  1530.  ***/
  1531. private void 
  1532. stc_freedata(stc_t *stc)
  1533. {
  1534.    int i,j;
  1535.  
  1536.    for(i = 0; i < 4; ++i) {
  1537.       if(stc->code[i] != NULL) {
  1538.  
  1539.          for(j = 0; j < i; ++j) if(stc->code[i] == stc->code[j]) break;
  1540.  
  1541.          if(i == j) gs_free(stc->code[i],1<<stc->bits,sizeof(gx_color_value),
  1542.                            "stcolor/code");
  1543.       }
  1544.  
  1545.       if(stc->vals[i] != NULL) {
  1546.  
  1547.          for(j = 0; j < i; ++j)
  1548.             if(stc->vals[i] == stc->vals[j]) break;
  1549.  
  1550.          if(i == j) gs_free(stc->vals[i],1<<stc->bits,sd->stc.alg_item,
  1551.                            "stcolor/transfer");
  1552.       }
  1553.    }
  1554.  
  1555.    for(i = 0; i < 4; ++i) {
  1556.       stc->code[i] = NULL;
  1557.       stc->vals[i] = NULL;
  1558.    }
  1559. }
  1560.  
  1561. /***
  1562.  *** open the device and initialize margins & arrays
  1563.  ***/
  1564.  
  1565. private int 
  1566. stc_open(gx_device *pdev) /* setup margins & arrays */
  1567. {
  1568.   stcolor_device *sd = (stcolor_device *) pdev;
  1569.   int i,j,code;
  1570.   gx_color_index white;
  1571.   byte *bpw,*bpm;
  1572.  
  1573.   code = 0;
  1574. /*
  1575.  * Establish Algorithm-Table, if not present
  1576.  */
  1577.   if(sd->stc.algorithms.size == 0) {
  1578.      gs_param_string *dp;
  1579.      for(i = 0; stc_dither[i].name != NULL; ++i); /* count 'em */
  1580.      sd->stc.algorithms.size = i;
  1581.      dp = gs_malloc(i,sizeof(gs_param_string),
  1582.                                         "stcolor/algorithms");
  1583.      if(dp == NULL) {
  1584.         code = gs_error_VMerror;
  1585.         sd->stc.algorithms.size = 0;
  1586.      } else {
  1587.         sd->stc.algorithms.data       = dp;
  1588.         sd->stc.algorithms.persistent = true;
  1589.         for(i = 0; stc_dither[i].name != NULL; ++i) {
  1590.         param_string_from_string(dp[i],stc_dither[i].name);
  1591.         }
  1592.      }
  1593.   }
  1594.  
  1595. # define stc_sizeofitem(T) sd->stc.alg_item = sizeof(T)
  1596.   STC_TYPESWITCH(sd->stc.dither,stc_sizeofitem)
  1597.  
  1598.   stc_print_setup(sd);
  1599.  
  1600. /*
  1601.  * Establish internal Value & Code-Arrays
  1602.  */
  1603.  
  1604.  
  1605.   for(i = 0; i < sd->color_info.num_components; ++i) { /* comp */
  1606.  
  1607.      if((sd->stc.sizc[i] >  1) && (sd->stc.extc[i] != NULL)) { /* code req. */
  1608.  
  1609.         for(j = 0; j < i; ++j) if(sd->stc.extc[i] == sd->stc.extc[j]) break;
  1610.  
  1611.         if(i == j) { /* new one */
  1612.            sd->stc.code[i] = gs_malloc(1<<sd->stc.bits,sizeof(gx_color_value),
  1613.                              "stcolor/code");
  1614.  
  1615.            if(sd->stc.code[i] == NULL) { /* error */
  1616.               code = gs_error_VMerror;
  1617.            } else {                      /* success */
  1618. /*
  1619.  * Try making things easier:
  1620.  *     normalize values to 0.0/1.0-Range
  1621.  *     X-Axis:   Color-Values (implied)
  1622.  *     Y-Values: Indices      (given)
  1623.  */
  1624.               unsigned long ly,iy;
  1625.               double ystep,xstep,fx,fy;
  1626.  
  1627. /* normalize */
  1628.  
  1629.               fx =  1e18;
  1630.               fy = -1e18;
  1631.               for(ly = 0; ly < sd->stc.sizc[i]; ++ly) {
  1632.                  if(sd->stc.extc[i][ly] < fx) fx = sd->stc.extc[i][ly];
  1633.                  if(sd->stc.extc[i][ly] > fy) fy = sd->stc.extc[i][ly];
  1634.               }
  1635.               if((fx != 0.0) || (fy != 1.0)) {
  1636.                  fy = 1.0 / (fy - fx);
  1637.                  for(ly = 0; ly < sd->stc.sizc[i]; ++ly)
  1638.                     sd->stc.extc[i][ly] = fy * (sd->stc.extc[i][ly]-fx);
  1639.               }
  1640.  
  1641. /* interpolate */
  1642.               ystep = 1.0 / (double)((1<<sd->stc.bits)-1);
  1643.               xstep = 1.0 / (double)( sd->stc.sizc[i] -1);
  1644.  
  1645.               iy = 0;
  1646.               for(ly = 0; ly < (1<<sd->stc.bits); ++ly) {
  1647.                  fy = ystep * ly;
  1648.                  while(((iy+1) < sd->stc.sizc[i]) &&
  1649.                        (  fy   > sd->stc.extc[i][iy+1])) ++iy;
  1650.                  fx  = iy + (fy - sd->stc.extc[i][iy])
  1651.                             / (sd->stc.extc[i][iy+1] - sd->stc.extc[i][iy]);
  1652.                  fx *= xstep * gx_max_color_value;
  1653.  
  1654.                  fx = fx < 0.0 ? 0.0 :
  1655.                       (fx > gx_max_color_value ? gx_max_color_value : fx);
  1656.  
  1657.                  sd->stc.code[i][ly] = fx;
  1658.                  if((fx-sd->stc.code[i][ly]) >= 0.5) sd->stc.code[i][ly] += 1;
  1659.               }
  1660.            }                             /* error || success */
  1661.  
  1662.         } else {     /* shared one */
  1663.  
  1664.            sd->stc.code[i] = sd->stc.code[j];
  1665.  
  1666.         }           /* new || shared one */
  1667.      }                                                         /* code req. */
  1668.  
  1669.      if((sd->stc.sizv[i] >  1) && (sd->stc.extv[i] != NULL)) { /* vals req. */
  1670.  
  1671.         for(j = 0; j < i; ++j)
  1672.            if((sd->stc.extc[i] == sd->stc.extc[j]) &&
  1673.               (sd->stc.extv[i] == sd->stc.extv[j])) break;
  1674.  
  1675.         if(i == j) { /* new one */
  1676.  
  1677.              sd->stc.vals[i] =
  1678.                 gs_malloc(1<<sd->stc.bits,sd->stc.alg_item,"stcolor/transfer");
  1679.  
  1680.            if(sd->stc.vals[i] == NULL) {
  1681.  
  1682.               code = gs_error_VMerror;
  1683.  
  1684.            } else {                      /* success */
  1685.  
  1686.  
  1687.               if(sd->stc.code[i] == NULL) { /* linear */
  1688.  
  1689.                  byte  *Out  = sd->stc.vals[i];
  1690.                  int    Nout = 1<<sd->stc.bits;
  1691.                  double Omin = sd->stc.dither->minmax[0];
  1692.                  double Omax = sd->stc.dither->minmax[1];
  1693.                  float *In   = sd->stc.extv[i];
  1694.                  int    Nin  = sd->stc.sizv[i];
  1695.                  unsigned long I,io;
  1696.                  double Istep,Ostep,Y;
  1697.                  byte   Ovb; long Ovl;
  1698.  
  1699.                  Istep = 1.0 / (double) ((Nin)-1);
  1700.                  Ostep = 1.0 / (double) ((Nout)-1);
  1701.  
  1702.                  for(io = 0; io < (Nout); ++io) {
  1703.                     I = (long)(io * ((Nin)-1))/((Nout)-1);
  1704.  
  1705.                     if((I+1) < (Nin))
  1706.                        Y = In[I] + (In[I+1]-In[I])
  1707.                                      * ((double) io * Ostep - (double)I * Istep)
  1708.                                                /  (double) Istep;
  1709.                     else
  1710.                        Y = In[I] + (In[I]-In[I-1])
  1711.                                      * ((double) io * Ostep - (double)I * Istep)
  1712.                                                /  (double) Istep;
  1713.  
  1714.                     Y = Omin + (Omax-Omin) * Y;
  1715.                     Y = Y < Omin ? Omin : (Y > Omax ? Omax : Y);
  1716.  
  1717.  
  1718.                     switch(sd->stc.dither->flags & STC_TYPE) {
  1719.                        case STC_BYTE:
  1720.                           Ovb = Y;
  1721.                           if(((Y-Ovb) >= 0.5) && ((Ovb+1) <= Omax)) Ovb += 1;
  1722.                           Out[io] = Ovb;
  1723.                           break;
  1724.                        case STC_LONG:
  1725.                           Ovl = Y;
  1726.                           if(((Y-Ovl) >= 0.5) && ((Ovl+1) <= Omax)) Ovl += 1;
  1727.                           if(((Ovl-Y) >= 0.5) && ((Ovl-1) >= Omax)) Ovl -= 1;
  1728.                           ((long *)Out)[io] = Ovl;
  1729.                           break;
  1730.                        default:
  1731.                           ((float *)Out)[io] = Y;
  1732.                           break;
  1733.                     }
  1734.                  }
  1735.  
  1736.               } else {                     /* encoded */
  1737.                  unsigned long j,o;
  1738.                  double xstep,x,y;
  1739.  
  1740.                  xstep = 1.0 / (double) (sd->stc.sizv[i]-1);
  1741.  
  1742. /*
  1743.  * The following differs in so far from the previous, that the desired
  1744.  * X-Values are stored in another array.
  1745.  */
  1746.                  for(o = 0; o < (1<<sd->stc.bits); ++o) { /* code-loop */
  1747.  
  1748.                     x = sd->stc.code[i][o]; x /= gx_max_color_value;
  1749.  
  1750.                     j = x / xstep;
  1751.  
  1752.                     if((j+1) < sd->stc.sizv[i]) {
  1753.                        y  = sd->stc.extv[i][j];
  1754.                        y += (sd->stc.extv[i][j+1]-y)*(x-(double)j*xstep)/xstep;
  1755.                     } else {
  1756.                        y  = sd->stc.extv[i][j];
  1757.                        y += (y-sd->stc.extv[i][j-1])*(x-(double)j*xstep)/xstep;
  1758.                     }
  1759.  
  1760.                     y = sd->stc.dither->minmax[0]
  1761.                       +(sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0])*y;
  1762.  
  1763. #                   define stc_adjvals(T)                                             \
  1764.                      ((T *)(sd->stc.vals[i]))[o] = y;                                 \
  1765.                                                                                       \
  1766.                     if(((y-((T *)(sd->stc.vals[i]))[o]) >= 0.5) &&                    \
  1767.                        ((1+((T *)(sd->stc.vals[i]))[o]) <= sd->stc.dither->minmax[1]))\
  1768.                        ((T *)(sd->stc.vals[i]))[o]      += 1;                         \
  1769.                                                                                       \
  1770.                     if(((((T *)(sd->stc.vals[i]))[o]-y) >= 0.5) &&                    \
  1771.                        ((((T *)(sd->stc.vals[i]))[o]-1) >= sd->stc.dither->minmax[0]))\
  1772.                        ((T *)(sd->stc.vals[i]))[o]      -= 1;
  1773.  
  1774.                     STC_TYPESWITCH(sd->stc.dither,stc_adjvals)
  1775.  
  1776. #                   undef stc_adjvals
  1777.                  }                                       /* code-loop */
  1778.               }                            /* lineaer / encoded */
  1779.            }                             /* error || success */
  1780.  
  1781.         } else {     /* shared one */
  1782.  
  1783.            sd->stc.vals[i] = sd->stc.vals[j];
  1784.  
  1785.         }           /* new || shared one */
  1786.      }                                                         /* vals req. */
  1787.   }                                                    /* comp */
  1788.  
  1789.   if(code == 0) {
  1790.  
  1791.       sd->stc.flags |= STCOK4GO;
  1792.  
  1793. /*
  1794.  * Arrgh: open-procedure seems to be the right-place, but it is
  1795.  *        necessary to establish the defaults for omitted procedures too.
  1796.  */
  1797.  
  1798.       switch(sd->color_info.num_components) { /* Establish color-procs */
  1799.       case 1:
  1800.          set_dev_proc(sd,map_rgb_color, stc_map_gray_color);
  1801.          set_dev_proc(sd,map_cmyk_color,gx_default_map_cmyk_color);
  1802.          set_dev_proc(sd,map_color_rgb, stc_map_color_gray);
  1803.          white = stc_map_gray_color((gx_device *) sd,
  1804.                     gx_max_color_value,gx_max_color_value,gx_max_color_value);
  1805.          break;
  1806.       case 3:
  1807.          set_dev_proc(sd,map_rgb_color, stc_map_rgb_color);
  1808.          set_dev_proc(sd,map_cmyk_color,gx_default_map_cmyk_color);
  1809.          set_dev_proc(sd,map_color_rgb, stc_map_color_rgb);
  1810.          white = stc_map_rgb_color((gx_device *) sd,
  1811.                     gx_max_color_value,gx_max_color_value,gx_max_color_value);
  1812.          break;
  1813.       default:
  1814.          set_dev_proc(sd,map_rgb_color, gx_default_map_rgb_color);
  1815.          if(sd->stc.flags & STCCMYK10) {
  1816.             set_dev_proc(sd,map_cmyk_color,stc_map_cmyk10_color);
  1817.             set_dev_proc(sd,map_color_rgb, stc_map_color_cmyk10);
  1818.             white = stc_map_cmyk10_color((gx_device *) sd,0,0,0,0);
  1819.          } else {
  1820.             set_dev_proc(sd,map_cmyk_color,stc_map_cmyk_color);
  1821.             set_dev_proc(sd,map_color_rgb, stc_map_color_cmyk);
  1822.             white = stc_map_cmyk_color((gx_device *) sd,0,0,0,0);
  1823.          }
  1824.          break;                               /* Establish color-procs */
  1825.       }
  1826.  
  1827.  
  1828. /*
  1829.  * create at least a Byte
  1830.  */
  1831.       if(sd->color_info.depth < 2) white |= (white<<1);
  1832.       if(sd->color_info.depth < 4) white |= (white<<2);
  1833.       if(sd->color_info.depth < 8) white |= (white<<4);
  1834.  
  1835. /*
  1836.  * copy the Bytes
  1837.  */
  1838.       bpw = (byte *) sd->stc.white_run;
  1839.  
  1840.       if(sd->color_info.depth < 16) {
  1841.          for(i = 0; i < sizeof(sd->stc.white_run); i += 1) {
  1842.             bpw[i] = 0xff & white;
  1843.          }
  1844.       } else if(sd->color_info.depth < 24) {
  1845.          for(i = 0; i < sizeof(sd->stc.white_run); i += 2) {
  1846.             bpw[i]   = 0xff & (white>>8);
  1847.             bpw[i+1] = 0xff &  white;
  1848.          }
  1849.       } else if(sd->color_info.depth < 32) {
  1850.          for(i = 0; i < sizeof(sd->stc.white_run); i += 3) {
  1851.             bpw[i]   = 0xff & (white>>16);
  1852.             bpw[i+1] = 0xff & (white>> 8);
  1853.             bpw[i+2] = 0xff &  white;
  1854.          }
  1855.       } else {
  1856.          for(i = 0; i < sizeof(sd->stc.white_run); i += 4) {
  1857.             bpw[i]   = 0xff & (white>>24);
  1858.             bpw[i+1] = 0xff & (white>>16);
  1859.             bpw[i+2] = 0xff & (white>> 8);
  1860.             bpw[i+3] = 0xff &  white;
  1861.          }
  1862.       }
  1863. /*
  1864.  *    compute the trailer
  1865.  */
  1866.       j  = sd->width -
  1867.           (dev_l_margin(sd)+dev_r_margin(sd))*sd->x_pixels_per_inch;
  1868.       j  = j * sd->color_info.depth;            /* the Bit-count */
  1869.       j  = j % (32*countof(sd->stc.white_run)); /* remaining Bits */
  1870.  
  1871.       bpm = (byte *) sd->stc.white_end;
  1872.       for(i = 0; i < (4*countof(sd->stc.white_end)); ++i) {
  1873.          if(       j <= 0) {
  1874.             bpm[i] = 0;
  1875.          } else if(j >= 8) {
  1876.             bpm[i] = 0xff;
  1877.             j -= 8;
  1878.          } else {
  1879.             bpm[i] = 0xff ^ ((1<<(8-j))-1);
  1880.             j  = 0;
  1881.          }
  1882.          bpm[i] &= bpw[i];
  1883.       }
  1884.  
  1885. /*
  1886.  * Call super-class open
  1887.  */
  1888.  
  1889.       return gdev_prn_open(pdev);
  1890.  
  1891.    } else {
  1892.  
  1893.       stc_freedata(&sd->stc);
  1894.  
  1895.       return_error(code);
  1896.    }
  1897.  
  1898. }
  1899.  
  1900. /***
  1901.  *** stc_close: release the internal data
  1902.  ***/
  1903. private int 
  1904. stc_close(gx_device *pdev)
  1905. {
  1906.    stc_freedata(&((stcolor_device *) pdev)->stc);
  1907.    ((stcolor_device *) pdev)->stc.flags &= ~STCOK4GO;
  1908.    return gdev_prn_close(pdev);
  1909. }
  1910.  
  1911.  
  1912. /***
  1913.  *** Function for Bit-Truncation, including direct-byte-transfer
  1914.  ***/
  1915. private gx_color_value 
  1916. stc_truncate(stcolor_device *sd,int i,gx_color_value v)
  1917. {
  1918.  
  1919.    if(sd->stc.bits < gx_color_value_bits) {
  1920.       if(sd->stc.code[i] != NULL) {
  1921. /*
  1922.  * Perform binary search in the code-array
  1923.  */
  1924.          long  s;
  1925.          gx_color_value *p;
  1926.  
  1927.          s = sd->stc.bits > 1 ? 1L<<(sd->stc.bits-2) : 0L;
  1928.          p = sd->stc.code[i]+(1L<<(sd->stc.bits-1));
  1929.  
  1930.          while(s > 0) {
  1931.             if(v > *p) {
  1932.                p += s;
  1933.             } else if(v < p[-1]) {
  1934.                p -= s;
  1935.             } else {
  1936.                if((v-p[-1]) < (p[0]-v)) p -= 1;
  1937.                break;
  1938.             }
  1939.             s >>= 1;
  1940.          }
  1941.          if((v-p[-1]) < (p[0]-v)) p -= 1;
  1942.          v = p - sd->stc.code[i];
  1943.  
  1944.       } else {
  1945.  
  1946.          v >>= gx_color_value_bits-sd->stc.bits;
  1947.  
  1948.       }
  1949.  
  1950. /*
  1951.       V = (((1L<<D->stc.bits)-1)*V+(gx_max_color_value>>1))\
  1952.           /gx_max_color_value;                             \
  1953. */
  1954.    }
  1955.    return v;
  1956. }
  1957.  
  1958. private gx_color_value
  1959. stc_truncate1(stcolor_device *sd,int i,gx_color_value v)
  1960. {
  1961.  
  1962.    return sd->stc.vals[i][stc_truncate(sd,i,v)];
  1963. }
  1964.  
  1965. /***
  1966.  *** Expansion of indices for reverse-mapping
  1967.  ***/
  1968. private gx_color_value 
  1969. stc_expand(stcolor_device *sd,int i,gx_color_index col)
  1970. {
  1971.  
  1972.    gx_color_index cv;
  1973.    gx_color_index l = (1<<sd->stc.bits)-1;
  1974.  
  1975.    if(sd->stc.code[i] != NULL) {
  1976.  
  1977.       cv  = sd->stc.code[i][col & l];
  1978.  
  1979.    } else if(sd->stc.bits < gx_color_value_bits) {
  1980.  
  1981.       cv  = (col & l)<<(gx_color_value_bits-sd->stc.bits);
  1982.       cv += (col & l)/l * ((1<<(gx_color_value_bits-sd->stc.bits))-1);
  1983.  
  1984.    } else if(sd->stc.bits > gx_color_value_bits) {
  1985.  
  1986.       cv  = (col & l)>>(sd->stc.bits-gx_color_value_bits);
  1987.  
  1988.    } else {
  1989.  
  1990.       cv  = col & l;
  1991.  
  1992.    }
  1993.  
  1994.    return cv;
  1995. }
  1996.  
  1997. /***
  1998.  *** color-mapping of gray-scales
  1999.  ***/
  2000. private gx_color_index 
  2001. stc_map_gray_color(gx_device *pdev,
  2002.         gx_color_value r, gx_color_value g, gx_color_value b)
  2003. {
  2004.  
  2005.    stcolor_device *sd = (stcolor_device *) pdev;
  2006.    gx_color_index rv;
  2007.  
  2008.    if((r == g) && (g == b)) {
  2009.  
  2010.       rv = gx_max_color_value - r;
  2011.  
  2012.    } else if(sd->stc.am != NULL) {
  2013.       float *m,fv;
  2014.  
  2015.       m   = sd->stc.am;
  2016.  
  2017.       fv  = gx_max_color_value;
  2018.       fv -= *m++ * (float) r; fv -= *m++ * (float) g; fv -= *m   * (float) b;
  2019.  
  2020.       if(     fv < 0.0)                      rv = 0;
  2021.       else if((fv+0.5) > gx_max_color_value) rv = gx_max_color_value;
  2022.       else                                   rv = fv+0.5;
  2023.  
  2024.    } else {
  2025.  
  2026.       rv  = ((gx_color_index)gx_max_color_value)<<3;
  2027.       rv -= (gx_color_index) 3 * r;
  2028.       rv -= (gx_color_index) 3 * g;
  2029.       rv -= ((gx_color_index)b)<<1;
  2030.       rv  = (rv+4)>>3;
  2031.       if(rv > gx_max_color_value) rv = gx_max_color_value;
  2032.  
  2033.    }
  2034.  
  2035.    if(( sd->stc.bits                      ==    8) &&
  2036.       ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE))
  2037.       rv = stc_truncate1(sd,0,(gx_color_value)rv);
  2038.    else
  2039.       rv =  stc_truncate(sd,0,(gx_color_value)rv);
  2040.  
  2041.    return rv;
  2042. }
  2043.  
  2044. private int 
  2045. stc_map_color_gray(gx_device *pdev, gx_color_index color,gx_color_value prgb[3])
  2046. {
  2047.    stcolor_device *sd = (stcolor_device *) pdev;
  2048.    gx_color_index l = ((gx_color_index)1<<sd->stc.bits)-1;
  2049.  
  2050.    prgb[0] = gx_max_color_value - stc_expand(sd,0,color & l);
  2051.    prgb[1] = prgb[0]; prgb[2] = prgb[0];
  2052.  
  2053.    return 0;
  2054. }
  2055.  
  2056. /***
  2057.  *** color-mapping of rgb-values
  2058.  ***/
  2059. private gx_color_index 
  2060. stc_map_rgb_color(gx_device *pdev,
  2061.                   gx_color_value r, gx_color_value g, gx_color_value b)
  2062. {
  2063.  
  2064.    stcolor_device *sd = (stcolor_device *) pdev;
  2065.    int          shift = sd->color_info.depth == 24 ? 8 : sd->stc.bits;
  2066.    gx_color_index  rv = 0;
  2067.  
  2068.    if((sd->stc.am != NULL) && ((r != g) || (g != b))) {
  2069.       float *m,fr,fg,fb,fv;
  2070.  
  2071.       m  = sd->stc.am;
  2072.       fr = r; fg = g; fb = b;
  2073.  
  2074.       fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
  2075.  
  2076.       if(     fv < 0.0)                      r = 0;
  2077.       else if((fv+0.5) > gx_max_color_value) r = gx_max_color_value;
  2078.       else                                   r = fv+0.5;
  2079.  
  2080.       fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
  2081.  
  2082.       if(     fv < 0.0)                      g = 0;
  2083.       else if((fv+0.5) > gx_max_color_value) g = gx_max_color_value;
  2084.       else                                   g = fv+0.5;
  2085.  
  2086.       fv = *m++ * fr; fv += *m++ * fg; fv += *m++ * fb;
  2087.  
  2088.       if(     fv < 0.0)                      b = 0;
  2089.       else if((fv+0.5) > gx_max_color_value) b = gx_max_color_value;
  2090.       else                                   b = fv+0.5;
  2091.  
  2092.    }
  2093.  
  2094.    if(( sd->stc.bits                      ==    8) &&
  2095.       ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
  2096.       rv =               stc_truncate1(sd,0,r);
  2097.       rv = (rv<<shift) | stc_truncate1(sd,1,g);
  2098.       rv = (rv<<shift) | stc_truncate1(sd,2,b);
  2099.    } else {
  2100.       rv =                stc_truncate(sd,0,r);
  2101.       rv = (rv<<shift) |  stc_truncate(sd,1,g);
  2102.       rv = (rv<<shift) |  stc_truncate(sd,2,b);
  2103.    }
  2104.  
  2105.    return rv;
  2106. }
  2107.  
  2108. private int 
  2109. stc_map_color_rgb(gx_device *pdev, gx_color_index color,gx_color_value prgb[3])
  2110. {
  2111.  
  2112.    stcolor_device *sd = (stcolor_device *) pdev;
  2113.    int          shift = sd->color_info.depth == 24 ? 8 : sd->stc.bits;
  2114.    gx_color_index l =   ((gx_color_index)1<<sd->stc.bits)-1;
  2115.  
  2116.    prgb[0] = stc_expand(sd,0,((color>>(shift<<1)) & l));
  2117.    prgb[1] = stc_expand(sd,1,((color>> shift    ) & l));
  2118.    prgb[2] = stc_expand(sd,2,( color              & l));
  2119.  
  2120.    return 0;
  2121. }
  2122.  
  2123. /***
  2124.  *** color-mapping of cmyk-values
  2125.  ***/
  2126. private gx_color_index 
  2127. stc_map_cmyk_color(gx_device *pdev,
  2128.         gx_color_value c, gx_color_value m, gx_color_value y,gx_color_value k)
  2129. {
  2130.  
  2131.    stcolor_device *sd = (stcolor_device *) pdev;
  2132.    int          shift = sd->color_info.depth == 32 ? 8 : sd->stc.bits;
  2133.    gx_color_index rv = 0;
  2134.  
  2135.    if((c == m) && (m == y)) {
  2136.  
  2137.       k = c > k ? c : k;
  2138.       c = m = y = 0;
  2139.  
  2140.       if(( sd->stc.bits                      ==    8) &&
  2141.       ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
  2142.          k  = stc_truncate1(sd,3,k);
  2143.       } else {
  2144.          k  =  stc_truncate(sd,3,k);
  2145.       }
  2146.  
  2147.    } else {
  2148.  
  2149.       if(sd->stc.am != NULL) {
  2150.  
  2151.          float *a,fc,fm,fy,fk,fv;
  2152.  
  2153.          if(k == 0) { /* no separated black yet */
  2154.             k  = c < m ? c : m;
  2155.             k  = k < y ? k : y;
  2156.             if(k) { /* no black at all */
  2157.                c -= k;
  2158.                m -= k;
  2159.                y -= k;
  2160.            }       /* no black at all */
  2161.          }            /* no separated black yet */
  2162.  
  2163.          a  = sd->stc.am;
  2164.          fc = c; fm = m; fy = y; fk = k;
  2165.  
  2166.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2167.          if(     fv < 0.0)                      c = 0;
  2168.          else if((fv+0.5) > gx_max_color_value) c = gx_max_color_value;
  2169.          else                                   c = fv+0.5;
  2170.  
  2171.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2172.          if(     fv < 0.0)                      m = 0;
  2173.          else if((fv+0.5) > gx_max_color_value) m = gx_max_color_value;
  2174.          else                                   m = fv+0.5;
  2175.  
  2176.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2177.          if(     fv < 0.0)                      y = 0;
  2178.          else if((fv+0.5) > gx_max_color_value) y = gx_max_color_value;
  2179.          else                                   y = fv+0.5;
  2180.  
  2181.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2182.          if(     fv < 0.0)                      k = 0;
  2183.          else if((fv+0.5) > gx_max_color_value) k = gx_max_color_value;
  2184.          else                                   k = fv+0.5;
  2185.  
  2186.       } else if(k == 0) {
  2187.  
  2188.          k  = c < m ? c : m;
  2189.          k  = k < y ? k : y;
  2190.       }
  2191.  
  2192.       if(( sd->stc.bits                      ==    8) &&
  2193.          ((sd->stc.dither->flags & STC_TYPE) == STC_BYTE)) {
  2194.          c = stc_truncate1(sd,0,c);
  2195.          m = stc_truncate1(sd,1,m);
  2196.          y = stc_truncate1(sd,2,y);
  2197.          k = stc_truncate1(sd,3,k);
  2198.       } else {
  2199.          c = stc_truncate(sd,0,c);
  2200.          m = stc_truncate(sd,1,m);
  2201.          y = stc_truncate(sd,2,y);
  2202.          k = stc_truncate(sd,3,k);
  2203.       }
  2204.    }
  2205.  
  2206.    rv =               c;
  2207.    rv = (rv<<shift) | m;
  2208.    rv = (rv<<shift) | y;
  2209.    rv = (rv<<shift) | k;
  2210.  
  2211.    if(rv == gx_no_color_index) rv ^= 1;
  2212.  
  2213.    return rv;
  2214. }
  2215.  
  2216. private int 
  2217. stc_map_color_cmyk(gx_device *pdev, gx_color_index color,gx_color_value prgb[3])
  2218. {
  2219.  
  2220.    stcolor_device *sd = (stcolor_device *) pdev;
  2221.    int          shift = sd->color_info.depth == 32 ? 8 : sd->stc.bits;
  2222.    gx_color_index   l = ((gx_color_index)1<<sd->stc.bits)-1;
  2223.    gx_color_value c,m,y,k;
  2224.  
  2225.    k = stc_expand(sd,3, color & l); color >>= shift;
  2226.    y = stc_expand(sd,2, color & l); color >>= shift;
  2227.    m = stc_expand(sd,1, color & l); color >>= shift;
  2228.    c = stc_expand(sd,0, color & l);
  2229.  
  2230.    if((c == m) && (m == y)) {
  2231.       prgb[0] = gx_max_color_value-k;
  2232.       prgb[1] = prgb[0];
  2233.       prgb[2] = prgb[0];
  2234.    } else {
  2235.       prgb[0] = gx_max_color_value-c;
  2236.       prgb[1] = gx_max_color_value-m;
  2237.       prgb[2] = gx_max_color_value-y;
  2238.    }
  2239.    return 0;
  2240. }
  2241.  
  2242. /***
  2243.  *** color-mapping of cmyk10-values
  2244.  ***/
  2245. private gx_color_index 
  2246. stc_map_cmyk10_color(gx_device *pdev,
  2247.         gx_color_value c, gx_color_value m, gx_color_value y,gx_color_value k)
  2248. {
  2249.  
  2250.    stcolor_device *sd = (stcolor_device *) pdev;
  2251.    int             mode;
  2252.    gx_color_index rv  = 0;
  2253.  
  2254.    if((c == m) && (m == y)) {
  2255.  
  2256.       k = c > k ? c : k;
  2257.       c = m = y = 0;
  2258.       mode = 3;
  2259.  
  2260.    } else {
  2261.  
  2262.       if(sd->stc.am != NULL) {
  2263.  
  2264.          float *a,fc,fm,fy,fk,fv;
  2265.  
  2266.          k  = c < m ? c : m;
  2267.          k  = k < y ? k : y;
  2268.          if(k) { /* no black at all */
  2269.             c -= k;
  2270.             m -= k;
  2271.             y -= k;
  2272.          }       /* no black at all */
  2273.  
  2274.          a  = sd->stc.am;
  2275.          fc = c; fm = m; fy = y; fk = k;
  2276.  
  2277.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2278.          if(     fv < 0.0)                      c = 0;
  2279.          else if((fv+0.5) > gx_max_color_value) c = gx_max_color_value;
  2280.          else                                   c = fv+0.5;
  2281.  
  2282.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2283.          if(     fv < 0.0)                      m = 0;
  2284.          else if((fv+0.5) > gx_max_color_value) m = gx_max_color_value;
  2285.          else                                   m = fv+0.5;
  2286.  
  2287.          fv = *a++ * fc; fv += *a++ * fm; fv += *a++ * fy; fv += *a++ * fk;
  2288.          if(     fv < 0.0)                      y = 0;
  2289.          else if((fv+0.5) > gx_max_color_value) y = gx_max_color_value;
  2290.          else                                   y = fv+0.5;
  2291.  
  2292.       }
  2293.  
  2294.       if(c < m) {
  2295.         if(c < y) { k = c; c = 0; mode = 0; }
  2296.         else      { k = y; y = 0; mode = 2; }
  2297.       } else {
  2298.         if(m < y) { k = m; m = 0; mode = 1; }
  2299.         else      { k = y; y = 0; mode = 2; }
  2300.       }
  2301.    }
  2302.  
  2303. /*
  2304.  * truncate only the values that require it
  2305.  */
  2306.    if(c) c = stc_truncate(sd,0,c);
  2307.    if(m) m = stc_truncate(sd,1,m);
  2308.    if(y) y = stc_truncate(sd,2,y);
  2309.    if(k) k = stc_truncate(sd,3,k);
  2310.  
  2311. /*
  2312.  * make sure that truncation-white becomes white.
  2313.  */
  2314.    if((c|m|y) == 0) mode = 3;
  2315.  
  2316. /*
  2317.  * check wether value-arrays can be bypassed
  2318.  */
  2319.    if(((sd->stc.dither->flags & STC_TYPE) == STC_BYTE) &&
  2320.       ( sd->stc.dither->minmax[0]         ==    0.0 )) {
  2321.       c = sd->stc.vals[0][c];
  2322.       m = sd->stc.vals[1][m];
  2323.       y = sd->stc.vals[2][y];
  2324.       k = sd->stc.vals[3][k];
  2325.    } else if(((sd->stc.dither->flags & STC_TYPE) == STC_LONG) &&
  2326.              ( sd->stc.dither->minmax[0]         ==     0.0 ) &&
  2327.              ( sd->stc.dither->minmax[1]         <=  1023.0 )) {
  2328.       c = ((long *)(sd->stc.vals[0]))[c];
  2329.       m = ((long *)(sd->stc.vals[1]))[m];
  2330.       y = ((long *)(sd->stc.vals[2]))[y];
  2331.       k = ((long *)(sd->stc.vals[3]))[k];
  2332.    }                                                       /* direct */
  2333. /*
  2334.  * compute the long-representation of gx_color_index
  2335.  */
  2336.    switch(mode) {
  2337.    case 0:
  2338.       rv = (((gx_color_index) m)<<22)|
  2339.            (((gx_color_index) y)<<12)|
  2340.            (((gx_color_index) k)<< 2)|mode;
  2341.       break;
  2342.    case 1:
  2343.       rv = (((gx_color_index) c)<<22)|
  2344.            (((gx_color_index) y)<<12)|
  2345.            (((gx_color_index) k)<< 2)|mode;
  2346.       break;
  2347.    case 2:
  2348.       rv = (((gx_color_index) c)<<22)|
  2349.            (((gx_color_index) m)<<12)|
  2350.            (((gx_color_index) k)<< 2)|mode;
  2351.       break;
  2352.    default:
  2353.       rv = (((gx_color_index) k)<< 2)|mode;
  2354.       break;
  2355.    }
  2356.  
  2357. /*
  2358.  * We may need some swapping
  2359.  */
  2360. #if !arch_is_big_endian
  2361.    {
  2362.       union { stc_pixel cv; byte bv[4]; } ui,uo;
  2363.       ui.cv = rv;
  2364.       uo.bv[0] = ui.bv[3];
  2365.       uo.bv[1] = ui.bv[2];
  2366.       uo.bv[2] = ui.bv[1];
  2367.       uo.bv[3] = ui.bv[0];
  2368.       rv       = uo.cv;
  2369.    }
  2370. #endif
  2371.    return rv;
  2372. }
  2373.  
  2374. private int 
  2375. stc_map_color_cmyk10(gx_device *pdev, gx_color_index color,
  2376.                      gx_color_value prgb[3])
  2377. {
  2378.  
  2379.    stcolor_device *sd = (stcolor_device *) pdev;
  2380.    gx_color_value c,m,y;
  2381.  
  2382. /*
  2383.  * We may need some swapping
  2384.  */
  2385. #if !arch_is_big_endian
  2386.    union { stc_pixel cv; byte bv[4]; } ui,uo;
  2387.    ui.cv = color;
  2388.    uo.bv[0] = ui.bv[3];
  2389.    uo.bv[1] = ui.bv[2];
  2390.    uo.bv[2] = ui.bv[1];
  2391.    uo.bv[3] = ui.bv[0];
  2392.    color    = uo.cv;
  2393. #endif
  2394.  
  2395.    c    =   stc_expand(sd,3,(color>>2)&0x3ff);
  2396.  
  2397.    switch(color & 3) {
  2398.      case 0:
  2399.         m = stc_expand(sd,1,(color>>22) & 0x3ff);
  2400.         y = stc_expand(sd,2,(color>>12) & 0x3ff);
  2401.         break;
  2402.      case 1:
  2403.         m = c;
  2404.         c = stc_expand(sd,0,(color>>22) & 0x3ff);
  2405.         y = stc_expand(sd,2,(color>>12) & 0x3ff);
  2406.         break;
  2407.      case 2:
  2408.         y = c;
  2409.         c = stc_expand(sd,0,(color>>22) & 0x3ff);
  2410.         m = stc_expand(sd,1,(color>>12) & 0x3ff);
  2411.         break;
  2412.      default:
  2413.         m = c;
  2414.         y = c;
  2415.         break;
  2416.    }
  2417.  
  2418.    prgb[0] = gx_max_color_value - c;
  2419.    prgb[1] = gx_max_color_value - m;
  2420.    prgb[2] = gx_max_color_value - y;
  2421.  
  2422.    return 0;
  2423. }
  2424.  
  2425. /***
  2426.  *** Macros for parameter-handling
  2427.  ***/
  2428.  
  2429. #define set_param_array(A, D, S)\
  2430.     {A.data = D; A.size = S; A.persistent = false;}
  2431.  
  2432. #define stc_write_null(N)                        \
  2433.     set_param_array(pfa,defext,countof(defext))  \
  2434.     code = param_write_null(plist,N);            \
  2435.     if (code < 0) return code;
  2436.  
  2437. #define stc_write_xarray(I,Coding,Transfer)                  \
  2438.     if(sd->stc.sizc[I] > 0) {                                \
  2439.        set_param_array(pfa, sd->stc.extc[I],sd->stc.sizc[I]) \
  2440.        code = param_write_float_array(plist,Coding,&pfa);    \
  2441.     } else {                                                 \
  2442.        code = param_write_null(plist,Coding);                \
  2443.     }                                                        \
  2444.     if ( code < 0 ) return code;                             \
  2445.                                                              \
  2446.     if(sd->stc.sizv[I] > 0)                                  \
  2447.        set_param_array(pfa, sd->stc.extv[I],sd->stc.sizv[I]) \
  2448.     else                                                     \
  2449.        set_param_array(pfa,defext,countof(defext))           \
  2450.     code = param_write_float_array(plist,Transfer,&pfa);     \
  2451.     if ( code < 0 ) return code;
  2452.  
  2453. #define stc_read_null(N)                                   \
  2454.     code = param_read_null(plist,N);                       \
  2455.     if(code == gs_error_typecheck)                         \
  2456.        code = param_read_float_array(plist,N,&pfa);        \
  2457.     if(code < 0) param_signal_error(plist,N,code);         \
  2458.     error = error > code ? code : error;
  2459.  
  2460. #define stc_read_xarray(I,Coding,Transfer)                 \
  2461.     code = param_read_float_array(plist,Coding,&pfa);      \
  2462.     if((error == 0) && (code == 0)) {                      \
  2463.        if(pfa.size > 1) {                                  \
  2464.           sd->stc.extc[I] = (float *) pfa.data;            \
  2465.           sd->stc.sizc[I] = pfa.size;                      \
  2466.        } else {                                            \
  2467.           code = gs_error_rangecheck;                      \
  2468.        }                                                   \
  2469.     } else if(code < 0) {                                  \
  2470.        code = param_read_null(plist,Coding);               \
  2471.        if(code == 0) {                                     \
  2472.           sd->stc.extc[I] = NULL;                          \
  2473.           sd->stc.sizc[I] = 0;                             \
  2474.        }                                                   \
  2475.     }                                                      \
  2476.     if(code < 0) param_signal_error(plist,Coding,code);    \
  2477.     error = error > code ? code : error;                   \
  2478.     code = param_read_float_array(plist,Transfer,&pfa);    \
  2479.     if((error == 0) && (code == 0)) {                      \
  2480.        sd->stc.extv[I] = (float *) pfa.data;               \
  2481.        sd->stc.sizv[I] = pfa.size;                         \
  2482.     } else if(code < 0) {                                  \
  2483.        code = param_read_null(plist,Transfer);             \
  2484.        if(code == 0) {                                     \
  2485.           sd->stc.extv[I] = defext;                        \
  2486.           sd->stc.sizv[I] = countof(defext);               \
  2487.        }                                                   \
  2488.     }                                                      \
  2489.     if(code < 0) param_signal_error(plist,Transfer,code);  \
  2490.     error = error > code ? code : error;
  2491.  
  2492. /***
  2493.  *** Get parameters == Make them accessable via PostScript
  2494.  ***/
  2495.  
  2496. private int 
  2497. stc_get_params(gx_device *pdev, gs_param_list *plist)
  2498. {
  2499.    int code,nc;
  2500.    gs_param_string      ps;
  2501.    gs_param_float_array pfa;
  2502.    bool btmp;
  2503.    stcolor_device *sd = (stcolor_device *) pdev;
  2504.  
  2505.    code = gdev_prn_get_params(pdev, plist);
  2506.    if ( code < 0 ) return code;
  2507.  
  2508. /*
  2509.  * Export some readonly-Parameters, used by stcinfo.ps
  2510.  */
  2511.    param_string_from_string(ps,"1.91");
  2512.    code = param_write_string(plist,"Version",&ps);
  2513.    if ( code < 0 ) return code;
  2514.  
  2515.    code = param_write_int(plist,"BitsPerComponent",&sd->stc.bits);
  2516.    if ( code < 0 ) return code;
  2517.  
  2518.    if(sd->stc.algorithms.size > 0) {
  2519.      code = param_write_string_array(plist,"Algorithms",&sd->stc.algorithms);
  2520.    } else {
  2521.      code = param_write_null(plist,"Algorithms");
  2522.    }
  2523.    if ( code < 0 ) return code;
  2524.  
  2525. /*
  2526.  * Export OutputCode
  2527.  */
  2528.    switch(sd->stc.flags & STCCOMP) {
  2529.    case STCPLAIN: param_string_from_string(ps,"plain");     break;
  2530.    case STCDELTA: param_string_from_string(ps,"deltarow");  break;
  2531.    default:       param_string_from_string(ps,"runlength"); break;
  2532.    }
  2533.    code = param_write_string(plist,"OutputCode",&ps);
  2534.    if ( code < 0 ) return code;
  2535. /*
  2536.  * Export Model
  2537.  */
  2538.    switch(sd->stc.flags & STCMODEL) {
  2539.    case STCST800: param_string_from_string(ps,"st800");   break;
  2540.    case STCSTCII: param_string_from_string(ps,"stcii");   break;
  2541.    default:       param_string_from_string(ps,"stc");     break;
  2542.    }
  2543.    code = param_write_string(plist,"Model",&ps);
  2544.    if ( code < 0 ) return code;
  2545.  
  2546. /*
  2547.  * Export the booleans
  2548.  */
  2549. #define stc_write_flag(Mask,Name)                \
  2550.    btmp = sd->stc.flags & (Mask) ? true : false; \
  2551.    code = param_write_bool(plist,Name,&btmp);    \
  2552.    if ( code < 0 ) return code;
  2553.  
  2554.    stc_write_flag(STCUNIDIR,"Unidirectional")
  2555.    stc_write_flag(STCUWEAVE,"Microweave")
  2556.    btmp = sd->stc.flags & (STCUNIDIR|STCUWEAVE) ? false : true;
  2557.    code = param_write_bool(plist,"Softweave",&btmp);
  2558.    if ( code < 0 ) return code;
  2559.    stc_write_flag(STCNWEAVE,"noWeave")
  2560.    stc_write_flag(STCDFLAG0, "Flag0")
  2561.    stc_write_flag(STCDFLAG1, "Flag1")
  2562.    stc_write_flag(STCDFLAG2, "Flag2")
  2563.    stc_write_flag(STCDFLAG3, "Flag3")
  2564.    stc_write_flag(STCDFLAG4, "Flag4")
  2565.  
  2566. #undef stc_write_flag
  2567.  
  2568. #  define stc_write_int(Mask,Name,Val)         \
  2569.       code = param_write_int(plist,Name,&Val); \
  2570.       if ( code < 0 ) return code
  2571.  
  2572.    stc_write_int(STCBAND,  "escp_Band",  sd->stc.escp_m);
  2573.    stc_write_int(STCWIDTH, "escp_Width", sd->stc.escp_width);
  2574.    stc_write_int(STCHEIGHT,"escp_Height",sd->stc.escp_height);
  2575.    stc_write_int(STCTOP,   "escp_Top",   sd->stc.escp_top);
  2576.    stc_write_int(STCBOTTOM,"escp_Bottom",sd->stc.escp_bottom);
  2577.  
  2578. #  undef stc_write_int
  2579.  
  2580.    code = param_write_string(plist,"escp_Init",&sd->stc.escp_init);
  2581.    code = param_write_string(plist,"escp_Release",&sd->stc.escp_release);
  2582.  
  2583.    if(sd->stc.dither != NULL) {
  2584.       param_string_from_string(ps,sd->stc.dither->name);
  2585.       code = param_write_string(plist,"Dithering",&ps);
  2586.    } else {
  2587.       code = param_write_null(plist,"Dithering");
  2588.    }
  2589.    if ( code < 0 ) return code;
  2590.  
  2591.    nc = sd->color_info.num_components;
  2592.  
  2593.    if(sd->stc.am != NULL) {
  2594.       if(     nc == 1) set_param_array(pfa, sd->stc.am, 3)
  2595.       else if(nc == 3) set_param_array(pfa, sd->stc.am, 9)
  2596.       else             set_param_array(pfa, sd->stc.am,16)
  2597.       code = param_write_float_array(plist,"ColorAdjustMatrix",&pfa);
  2598.    } else {
  2599.       code = param_write_null(plist,"ColorAdjustMatrix");
  2600.    }
  2601.    if ( code < 0 ) return code;
  2602.  
  2603.    if(nc == 1) {        /* DeviceGray */
  2604.  
  2605.       stc_write_xarray(0,"Kcoding","Ktransfer");
  2606.  
  2607.       stc_write_null("Rcoding"); stc_write_null("Rtransfer");
  2608.       stc_write_null("Gcoding"); stc_write_null("Gtransfer");
  2609.       stc_write_null("Bcoding"); stc_write_null("Btransfer");
  2610.  
  2611.       stc_write_null("Ccoding"); stc_write_null("Ctransfer");
  2612.       stc_write_null("Mcoding"); stc_write_null("Mtransfer");
  2613.       stc_write_null("Ycoding"); stc_write_null("Ytransfer");
  2614.  
  2615.    } else if(nc == 3) { /* DeviceRGB */
  2616.  
  2617.       stc_write_xarray(0,"Rcoding","Rtransfer");
  2618.       stc_write_xarray(1,"Gcoding","Gtransfer");
  2619.       stc_write_xarray(2,"Bcoding","Btransfer");
  2620.  
  2621.       stc_write_null("Ccoding"); stc_write_null("Ctransfer");
  2622.       stc_write_null("Mcoding"); stc_write_null("Mtransfer");
  2623.       stc_write_null("Ycoding"); stc_write_null("Ytransfer");
  2624.       stc_write_null("Kcoding"); stc_write_null("Ktransfer");
  2625.  
  2626.    } else {             /* DeviceCMYK */
  2627.  
  2628.       stc_write_xarray(0,"Ccoding","Ctransfer");
  2629.       stc_write_xarray(1,"Mcoding","Mtransfer");
  2630.       stc_write_xarray(2,"Ycoding","Ytransfer");
  2631.       stc_write_xarray(3,"Kcoding","Ktransfer");
  2632.  
  2633.       stc_write_null("Rcoding"); stc_write_null("Rtransfer");
  2634.       stc_write_null("Gcoding"); stc_write_null("Gtransfer");
  2635.       stc_write_null("Bcoding"); stc_write_null("Btransfer");
  2636.  
  2637.    }
  2638.    return code;
  2639. }
  2640.  
  2641. /***
  2642.  *** put parameters == Store them in the device-structure
  2643.  ***/
  2644.  
  2645. private int 
  2646. stc_put_params(gx_device *pdev, gs_param_list *plist)
  2647. {
  2648.    int code,error,i,l;
  2649.    bool b1,b2,b3;
  2650.    float fv,*fp;
  2651.    gs_param_string      ps;
  2652.    gs_param_string_array psa;
  2653.    gs_param_float_array pfa;
  2654.    stcolor_device *sd = (stcolor_device *) pdev;
  2655.    gx_device_color_info oldcolor;
  2656.    stc_t                oldstc;
  2657.  
  2658. /*
  2659.  * save old Values
  2660.  */
  2661.    memcpy(&oldcolor,&sd->color_info,sizeof(oldcolor));
  2662.    memcpy(&oldstc  ,&sd->stc       ,sizeof(oldstc  ));
  2663.  
  2664. /*
  2665.  * Arrrgh:
  2666.  * With Version 3.4x and above my simple minded read-only Parameters
  2667.  * do not work any more. So read them here for heavens sake.
  2668.  */
  2669.    code = param_read_string(plist,"Version",&ps);
  2670.    code = param_read_int(plist,"BitsPerComponent",&i);
  2671.    code = param_read_string_array(plist,"Algorithms",&psa);
  2672.  
  2673. /*
  2674.  * Fetch Major-Parameters (Model, Dithering, BitsPerPixel/BitsPerComponent)
  2675.  */
  2676.    error = 0;
  2677.  
  2678.    code  = param_read_string(plist,"Model",&ps);
  2679.    if(code == 0) {   /* Analyze the Model-String */
  2680. /*
  2681.  * Arrgh: I should have known, that internal strings are not zero-terminated.
  2682.  */
  2683.       for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
  2684. #     define stc_putcmp(Name) \
  2685.         ((strlen(Name) != l) || (0 != strncmp(Name, (const char *)ps.data,l)))
  2686.  
  2687.       sd->stc.flags &= ~STCMODEL;
  2688.       if(     !stc_putcmp("st800"))  sd->stc.flags |= STCST800;
  2689.       else if(!stc_putcmp("stcii"))  sd->stc.flags |= STCSTCII;
  2690.  
  2691.    }                 /* Analyze the Model-String */
  2692.    if(code < 0) param_signal_error(plist,"Model",code);
  2693.    error = error > code ? code : error;
  2694.  
  2695. /* If we're running for st800, #components must be 1 */
  2696.    if(((sd->stc.flags & STCMODEL) == STCST800) &&
  2697.       (( sd->color_info.num_components > 1) ||
  2698.        ( sd->stc.dither                == NULL) ||
  2699.        ((sd->stc.dither->flags & 7)    > 1))) {
  2700.         sd->color_info.num_components  = 1;
  2701.         sd->stc.dither = NULL;
  2702.     }
  2703.  
  2704. /* Weaving isn't a feature for the st800 */
  2705.    if((sd->stc.flags & STCMODEL) == STCST800) {
  2706.       sd->stc.flags &= ~STCUWEAVE;
  2707.       sd->stc.flags |=  STCNWEAVE;
  2708.    } else if((sd->stc.flags & STCMODEL) == STCSTCII) { /* no SoftWeave */
  2709.       sd->stc.flags |=  STCNWEAVE;
  2710.    }
  2711.  
  2712.    code  = param_read_string(plist,"Dithering",&ps);
  2713.    if(code == 0) {                     /* lookup new value new value */
  2714.  
  2715.       for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
  2716.  
  2717.       for(i = 0; stc_dither[i].name != NULL; ++i)
  2718.          if(!stc_putcmp(stc_dither[i].name)) break;
  2719.  
  2720.    } else if(sd->stc.dither != NULL) {  /* compute index of given value */
  2721.  
  2722.       i = sd->stc.dither - stc_dither;
  2723.  
  2724.    } else {                            /* find matching value */
  2725.  
  2726.       for(i = 0; stc_dither[i].name != NULL; ++i)
  2727.          if((stc_dither[i].flags & 7) == sd->color_info.num_components) break;
  2728.  
  2729.    }                                   /* we've got an index */
  2730.  
  2731.    if(stc_dither[i].name != NULL) { /* establish data */
  2732.  
  2733. /*
  2734.  * Establish new dithering algorithm & color-model
  2735.  */
  2736.       sd->stc.dither                = stc_dither+i;
  2737.       sd->color_info.num_components = sd->stc.dither->flags & 7;
  2738.   STC_TYPESWITCH(sd->stc.dither,stc_sizeofitem)
  2739. # undef stc_sizeofitem
  2740.       if(((sd->stc.flags & STCMODEL)    == STCST800) &&
  2741.          ( sd->color_info.num_components > 1       ))
  2742.          code = gs_error_rangecheck;
  2743.  
  2744. /*
  2745.  * reset Parameters related to the color-model, if it changed
  2746.  */
  2747.  
  2748.       if(sd->color_info.num_components != oldcolor.num_components) {
  2749.  
  2750.          for(i = 0; i < sd->color_info.num_components; ++i) {
  2751.             sd->stc.extv[i]   = (float *) defext;
  2752.             sd->stc.sizv[i]   = countof(defext);
  2753.  
  2754.             sd->stc.extc[i] = NULL;
  2755.             sd->stc.sizc[i] = 0;
  2756.  
  2757.          }
  2758.  
  2759.          sd->stc.am = NULL;
  2760.  
  2761.       } else { /* guarantee, that extvals is present */
  2762.  
  2763.          for(i = 0; i < sd->color_info.num_components; ++i) {
  2764.             if(sd->stc.sizv[i] < 2) {
  2765.                sd->stc.extv[i]   = (float *) defext;
  2766.                sd->stc.sizv[i]   = countof(defext);
  2767.             }
  2768.          }
  2769.       }
  2770.  
  2771.       for(i = sd->color_info.num_components; i < 4; ++ i) { /* clear unused */
  2772.          sd->stc.extv[i]   = NULL;
  2773.          sd->stc.sizv[i]   = 0;
  2774.          sd->stc.vals[i]   = NULL;
  2775.  
  2776.          sd->stc.extc[i] = NULL;
  2777.          sd->stc.sizc[i] = 0;
  2778.          sd->stc.code[i] = NULL;
  2779.  
  2780.       }                                                     /* clear unused */
  2781.  
  2782. /*
  2783.  * Guess default depth from range of values
  2784.  */
  2785.       if((sd->stc.dither != oldstc.dither)||(oldstc.vals[0] == NULL)) {
  2786.  
  2787.          if((sd->stc.dither->flags & STC_CMYK10) != 0) {
  2788.  
  2789.             sd->stc.flags       |= STCCMYK10;
  2790.             sd->stc.bits         = 10;
  2791.             sd->color_info.depth = 32;
  2792.  
  2793.          } else {
  2794.  
  2795.             sd->stc.flags       &= ~STCCMYK10;
  2796.  
  2797.             if((sd->stc.dither->flags & STC_FLOAT) != STC_FLOAT) {
  2798.                fv = 2.0;
  2799.                for(i = 1;(i  < gx_color_value_bits) &&
  2800.                   (fv <= (sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]));
  2801.                  ++i) fv *= 2.0;
  2802.  
  2803.             } else {
  2804.                i = 8; /* arbitrary */
  2805.             }
  2806.  
  2807.             if((i*sd->color_info.num_components) > (sizeof(stc_pixel)*8)) {
  2808.  
  2809.                sd->stc.bits         = (sizeof(stc_pixel)*8) /
  2810.                                        sd->color_info.num_components;
  2811.                sd->color_info.depth = sd->stc.bits * sd->color_info.num_components;
  2812.  
  2813.             } else {
  2814.  
  2815.                sd->stc.bits         = i;
  2816.                sd->color_info.depth = sd->stc.bits * sd->color_info.num_components;
  2817.  
  2818.             }
  2819.          }
  2820.       }
  2821.  
  2822.    } else {
  2823.  
  2824.       code = gs_error_rangecheck;
  2825.  
  2826.    }               /* verify new value */
  2827.    if(code < 0) param_signal_error(plist,"Dithering",code);
  2828.    error = error > code ? code : error;
  2829.  
  2830. /*
  2831.  * now fetch the desired depth, if the algorithm allows it
  2832.  */
  2833. /*
  2834.  * Arrrgh: We get code == 0, even if nobody sets BitsPerPixel.
  2835.  *         The value is the old one, but this may cause trouble
  2836.  *         with CMYK10.
  2837.  */
  2838.    code = param_read_int(plist, "BitsPerPixel", &i);
  2839.    if((error == 0) && (code == 0) &&
  2840.       (((sd->stc.flags & STCCMYK10) == 0) || (i != sd->color_info.depth))) {
  2841.  
  2842.       if((1 > i) || (i > (sizeof(stc_pixel)*8)))
  2843.          code = gs_error_rangecheck;
  2844.       else
  2845.          sd->color_info.depth = i;
  2846.  
  2847.       sd->stc.bits = i / sd->color_info.num_components;
  2848.  
  2849.       if(1 > sd->stc.bits) code = gs_error_rangecheck;
  2850.  
  2851.       if((sd->stc.dither->flags & STC_DIRECT) &&
  2852.          (sd->stc.dither->flags & STC_CMYK10))
  2853.          code           = gs_error_rangecheck;
  2854.       else
  2855.          sd->stc.flags &= ~STCCMYK10;
  2856.  
  2857.    }
  2858.    if(code < 0) param_signal_error(plist,"BitsPerPixel",code);
  2859.    error = error > code ? code : error;
  2860.  
  2861. /*
  2862.  * Fetch OutputCode
  2863.  */
  2864.    code  = param_read_string(plist,"OutputCode",&ps);
  2865.    if(code == 0) {   /* Analyze the OutputCode-String */
  2866.  
  2867.       for(l = ps.size; (l > 0) && (ps.data[l-1] == 0); --l);
  2868.  
  2869.       sd->stc.flags &= ~STCCOMP;
  2870.       if(!stc_putcmp("plain"))         sd->stc.flags |= STCPLAIN;
  2871.       else if(!stc_putcmp("deltarow")) sd->stc.flags |= STCDELTA;
  2872.  
  2873.    }                 /* Analyze the OutputCode-String */
  2874.    if((sd->stc.flags & STCCOMP) == STCDELTA) {
  2875.       sd->stc.flags |=  STCUWEAVE;
  2876.       sd->stc.flags &= ~STCNWEAVE;
  2877.    }
  2878.    if(code < 0) param_signal_error(plist,"OutputCode",code);
  2879.    error = error > code ? code : error;
  2880.  
  2881. /*
  2882.  * fetch the weave-mode (noWeave wins)
  2883.  */
  2884.    b1 = sd->stc.flags & STCUWEAVE ? true : false;
  2885.    b2 = sd->stc.flags & STCNWEAVE ? true : false;
  2886.    b3 = sd->stc.flags & (STCUWEAVE|STCNWEAVE) ? false : true;
  2887.  
  2888.    code = param_read_bool(plist,"Microweave",&b1);
  2889.    if(code < 0) {
  2890.       param_signal_error(plist,"Microweave",code);
  2891.    } else if(code == 0) {
  2892.       if(b1) { b2 = false; b3 = false; }
  2893.    }
  2894.    error = error > code ? code : error;
  2895.  
  2896.    code = param_read_bool(plist,"noWeave",&b2);
  2897.    if(code < 0) {
  2898.       param_signal_error(plist,"noWeave",code);
  2899.    } else if (code == 0) {
  2900.       if(b2) { b1 = false; b3 = false; }
  2901.    }
  2902.    error = error > code ? code : error;
  2903.  
  2904.    code = param_read_bool(plist,"Softweave",&b3);
  2905.    if(code < 0) {
  2906.       param_signal_error(plist,"Softweave",code);
  2907.    } else if (code == 0) {
  2908.       if(b3) { b1 = false; b2 = false; }
  2909.    }
  2910.    error = error > code ? code : error;
  2911.  
  2912.    if(b1) sd->stc.flags |=  STCUWEAVE;
  2913.    else   sd->stc.flags &= ~STCUWEAVE;
  2914.  
  2915.    if(b2) sd->stc.flags |=  STCNWEAVE;
  2916.    else   sd->stc.flags &= ~STCNWEAVE;
  2917.  
  2918. /*
  2919.  * Check the simple Flags
  2920.  */
  2921. #  define stc_read_flag(Mask,Name)                \
  2922.       code = param_read_bool(plist,Name,&b1);     \
  2923.       if(code < 0) {                              \
  2924.          param_signal_error(plist,Name,code);     \
  2925.       } else if(code == 0) {                      \
  2926.          if(b1 == true) sd->stc.flags |=  Mask;   \
  2927.          else           sd->stc.flags &= ~(Mask); \
  2928.       }                                           \
  2929.       error = error > code ? code : error;
  2930.  
  2931.    stc_read_flag(STCUNIDIR,"Unidirectional")
  2932.    stc_read_flag(STCDFLAG0, "Flag0")
  2933.    stc_read_flag(STCDFLAG1, "Flag1")
  2934.    stc_read_flag(STCDFLAG2, "Flag2")
  2935.    stc_read_flag(STCDFLAG3, "Flag3")
  2936.    stc_read_flag(STCDFLAG4, "Flag4")
  2937.  
  2938. /*
  2939.  * Now deal with the escp-Stuff
  2940.  */
  2941. #  define stc_read_int(Mask,Name,Val)             \
  2942.       code = param_read_int(plist,Name,&Val);     \
  2943.       if(code < 0)                                \
  2944.          param_signal_error(plist,Name,code);     \
  2945.       else if(code == 0)                          \
  2946.          sd->stc.flags |= Mask;                   \
  2947.       error = error > code ? code : error
  2948.  
  2949.    stc_read_int(STCBAND,  "escp_Band",  sd->stc.escp_m);
  2950.    stc_read_int(STCWIDTH, "escp_Width", sd->stc.escp_width);
  2951.    stc_read_int(STCHEIGHT,"escp_Height",sd->stc.escp_height);
  2952.    stc_read_int(STCTOP,   "escp_Top",   sd->stc.escp_top);
  2953.    stc_read_int(STCBOTTOM,"escp_Bottom",sd->stc.escp_bottom);
  2954.  
  2955. #  undef stc_read_int
  2956.  
  2957.    code = param_read_string(plist,"escp_Init",&sd->stc.escp_init);
  2958.    if(code == 0) sd->stc.flags |= STCINIT;
  2959.    error = error > code ? code : error;
  2960.  
  2961.    code = param_read_string(plist,"escp_Release",&sd->stc.escp_release);
  2962.    if(code == 0) sd->stc.flags |= STCRELEASE;
  2963.    error = error > code ? code : error;
  2964.  
  2965. /*
  2966.  * ColorAdjustMatrix must match the required size,
  2967.  * setting it explicitly to null, erases old matrix
  2968.  */
  2969.    code = param_read_float_array(plist,"ColorAdjustMatrix",&pfa);
  2970.    if((error == 0) && (code == 0)) {
  2971.       if(((sd->color_info.num_components == 1) && (pfa.size ==  3)) ||
  2972.          ((sd->color_info.num_components == 3) && (pfa.size ==  9)) ||
  2973.          ((sd->color_info.num_components == 4) && (pfa.size == 16)))
  2974.          sd->stc.am = (float *) pfa.data;
  2975.       else
  2976.          code =  gs_error_rangecheck;
  2977.    } else if(code < 0) {
  2978.       code = param_read_null(plist,"ColorAdjustMatrix");
  2979.       if(code == 0) sd->stc.am = NULL;
  2980.    }
  2981.    if(code < 0) param_signal_error(plist,"ColorAdjustMatrix",code);
  2982.    error = error > code ? code : error;
  2983.  
  2984. /*
  2985.  * Read the external array-Parameters
  2986.  */
  2987.    if(sd->color_info.num_components == 1) {        /* DeviceGray */
  2988.  
  2989.       stc_read_xarray(0,"Kcoding","Ktransfer");
  2990.  
  2991.       stc_read_null("Rcoding"); stc_read_null("Rtransfer");
  2992.       stc_read_null("Gcoding"); stc_read_null("Gtransfer");
  2993.       stc_read_null("Bcoding"); stc_read_null("Btransfer");
  2994.  
  2995.       stc_read_null("Ccoding"); stc_read_null("Ctransfer");
  2996.       stc_read_null("Mcoding"); stc_read_null("Mtransfer");
  2997.       stc_read_null("Ycoding"); stc_read_null("Ytransfer");
  2998.  
  2999.    } else if(sd->color_info.num_components == 3) { /* DeviceRGB */
  3000.  
  3001.       stc_read_xarray(0,"Rcoding","Rtransfer");
  3002.       stc_read_xarray(1,"Gcoding","Gtransfer");
  3003.       stc_read_xarray(2,"Bcoding","Btransfer");
  3004.  
  3005.       stc_read_null("Ccoding"); stc_read_null("Ctransfer");
  3006.       stc_read_null("Mcoding"); stc_read_null("Mtransfer");
  3007.       stc_read_null("Ycoding"); stc_read_null("Ytransfer");
  3008.       stc_read_null("Kcoding"); stc_read_null("Ktransfer");
  3009.  
  3010.    } else {                                        /* DeviceCMYK */
  3011.  
  3012.       stc_read_xarray(0,"Ccoding","Ctransfer");
  3013.       stc_read_xarray(1,"Mcoding","Mtransfer");
  3014.       stc_read_xarray(2,"Ycoding","Ytransfer");
  3015.       stc_read_xarray(3,"Kcoding","Ktransfer");
  3016.  
  3017.       stc_read_null("Rcoding"); stc_read_null("Rtransfer");
  3018.       stc_read_null("Gcoding"); stc_read_null("Gtransfer");
  3019.       stc_read_null("Bcoding"); stc_read_null("Btransfer");
  3020.  
  3021.    }
  3022. /*
  3023.  * Update remaining color_info values
  3024.  */
  3025.    if(error == 0) {
  3026.  
  3027. /*    compute #values from the component-bits */
  3028.       sd->color_info.max_gray  = sd->stc.bits < gx_color_value_bits ?
  3029.                             (1<<sd->stc.bits)-1 : gx_max_color_value;
  3030.  
  3031. /*    An integer-algorithm might reduce the number of values */
  3032.       if(((sd->stc.dither->flags & STC_TYPE) != STC_FLOAT) &&
  3033.          ((sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]) <
  3034.            sd->color_info.max_gray))
  3035.          sd->color_info.max_gray =
  3036.                 sd->stc.dither->minmax[1]-sd->stc.dither->minmax[0]+0.5;
  3037.  
  3038.       sd->color_info.max_color = sd->color_info.num_components < 3 ? 0 :
  3039.                                  sd->color_info.max_gray;
  3040.       sd->color_info.dither_grays =
  3041.           sd->color_info.max_gray < gx_max_color_value ?
  3042.           sd->color_info.max_gray+1  : gx_max_color_value;
  3043.       sd->color_info.dither_colors  = sd->color_info.num_components < 3 ? 0 :
  3044.           sd->color_info.dither_grays;
  3045.    }
  3046.  
  3047. /*
  3048.  * Call superclass-Update
  3049.  */
  3050.  
  3051.    code = gdev_prn_put_params(pdev, plist);
  3052.    error = error > code ? code : error;
  3053.  
  3054. /*
  3055.  * Arrrgh, writing BitsPerPixel is really *VERY* special:
  3056.  *    gdev_prn_put_params verifies, that the external value
  3057.  *    is written, if not, it raises a rangecheck-error.
  3058.  *    On the other hand ghostscript is quite unhappy with odd
  3059.  *    values, so we do the necessary rounding *AFTER* the
  3060.  *    "superclass-Update".
  3061.  */
  3062.  
  3063.    if(sd->color_info.depth ==  3) sd->color_info.depth = 4;
  3064.    else if(sd->color_info.depth > 4)
  3065.       sd->color_info.depth =  (sd->color_info.depth+7) & ~7;
  3066.  
  3067. /*
  3068.  * Allocate the storage for the arrays in memory
  3069.  */
  3070.    if(error == 0) { /* Allocate new external-arrays */
  3071.  
  3072.      for(i = 0; i < sd->color_info.num_components; ++i){ /* Active components */
  3073.         int j;
  3074.  
  3075.         if((sd->stc.extv[i] != oldstc.extv[i]) &&
  3076.            (sd->stc.extv[i] != defext        )) { /* Value-Arrays */
  3077.  
  3078.            for(j = 0; j < i; ++j)
  3079.               if((sd->stc.sizv[j] == sd->stc.sizv[i]) &&
  3080.                  (memcmp(sd->stc.extv[j],sd->stc.extv[i],
  3081.                          sd->stc.sizv[i]*sizeof(float)) == 0)) break;
  3082.  
  3083.            if(j < i) {
  3084.               sd->stc.extv[i] = sd->stc.extv[j];
  3085.            } else {
  3086.               fp = gs_malloc(sd->stc.sizv[i],sizeof(float),"stc_put_params");
  3087.               if(fp != NULL)
  3088.                  memcpy(fp,sd->stc.extv[i],sd->stc.sizv[i]*sizeof(float));
  3089.                else
  3090.                  code = gs_error_VMerror;
  3091.                sd->stc.extv[i] = fp;
  3092.            }
  3093.         }                                         /* Value-Arrays */
  3094.  
  3095.         if((sd->stc.sizc[i] > 1) &&
  3096.            (sd->stc.extc[i] != oldstc.extc[i])) { /* Code-Arrays */
  3097.  
  3098.            for(j = 0; j < i; ++j)
  3099.               if((sd->stc.sizc[j] == sd->stc.sizc[i]) &&
  3100.                  (memcmp(sd->stc.extc[j],sd->stc.extc[i],
  3101.                          sd->stc.sizc[i]*sizeof(float)) == 0)) break;
  3102.  
  3103.            if(j < i) {
  3104.               sd->stc.extc[i] = sd->stc.extc[j];
  3105.            } else {
  3106.               fp = gs_malloc(sd->stc.sizc[i],sizeof(float),"stc_put_params");
  3107.               if(fp != NULL)
  3108.                  memcpy(fp,sd->stc.extc[i],sd->stc.sizc[i]*sizeof(float));
  3109.                else
  3110.                  code = gs_error_VMerror;
  3111.                sd->stc.extc[i] = fp;
  3112.            }
  3113.         }                                         /* Code-Arrays */
  3114.  
  3115.      }                                                   /* Active components */
  3116.  
  3117.      if((sd->stc.am != NULL) && (sd->stc.am != oldstc.am)) {
  3118.         if(     sd->color_info.num_components == 1) i =  3;
  3119.         else if(sd->color_info.num_components == 3) i =  9;
  3120.         else                                        i = 16;
  3121.         fp = gs_malloc(i,sizeof(float),"stc_put_params");
  3122.         if(fp != NULL) memcpy(fp,sd->stc.am,i*sizeof(float));
  3123.         else           code = gs_error_VMerror;
  3124.         sd->stc.am = fp;
  3125.      }
  3126.  
  3127.      if(sd->stc.escp_init.data != oldstc.escp_init.data) {
  3128.         byte *ip = NULL;
  3129.  
  3130.         if(sd->stc.escp_init.size > 0) {
  3131.            ip = gs_malloc(sd->stc.escp_init.size,1,"stcolor/init");
  3132.            if(ip == NULL) {
  3133.               code = gs_error_VMerror;
  3134.               sd->stc.escp_init.size = 0;
  3135.            } else {
  3136.               memcpy(ip,sd->stc.escp_init.data,sd->stc.escp_init.size);
  3137.            }
  3138.         }
  3139.         sd->stc.escp_init.data       = ip;
  3140.         sd->stc.escp_init.persistent = false;
  3141.      }
  3142.  
  3143.      if(sd->stc.escp_release.data != oldstc.escp_release.data) {
  3144.         byte *ip = NULL;
  3145.  
  3146.         if(sd->stc.escp_release.size > 0) {
  3147.            ip = gs_malloc(sd->stc.escp_release.size,1,"stcolor/release");
  3148.            if(ip == NULL) {
  3149.               code = gs_error_VMerror;
  3150.               sd->stc.escp_release.size = 0;
  3151.            } else {
  3152.               memcpy(ip,sd->stc.escp_release.data,sd->stc.escp_release.size);
  3153.            }
  3154.         }
  3155.         sd->stc.escp_release.data       = ip;
  3156.         sd->stc.escp_release.persistent = false;
  3157.      }
  3158.  
  3159.      if(code < 0) { /* free newly allocated arrays */
  3160.  
  3161.         if((sd->stc.am != NULL) && (sd->stc.am != oldstc.am)) {
  3162.            if(     sd->color_info.num_components == 1) i =  3;
  3163.            else if(sd->color_info.num_components == 3) i =  9;
  3164.            else                                        i = 16;
  3165.            gs_free(sd->stc.am,i,sizeof(float),"stc_put_params");
  3166.         }
  3167.  
  3168.         if((sd->stc.escp_init.data != NULL) &&
  3169.            (sd->stc.escp_init.data != oldstc.escp_init.data))
  3170.            gs_free((byte *) sd->stc.escp_init.data,sd->stc.escp_init.size,1,
  3171.               "stcolor/init");
  3172.  
  3173.         if((sd->stc.escp_release.data != NULL) &&
  3174.            (sd->stc.escp_release.data != oldstc.escp_release.data))
  3175.            gs_free((byte *) sd->stc.escp_release.data,sd->stc.escp_release.
  3176.               size,1,"stcolor/release");
  3177.  
  3178.         for(i = 0; i < sd->color_info.num_components; ++i) { /* components */
  3179.            int j;
  3180.  
  3181.            if((sd->stc.extc[i] != NULL) &&
  3182.               (sd->stc.extc[i] != defext) &&
  3183.               (sd->stc.extc[i] != oldstc.extc[i])) {
  3184.  
  3185.               for(j = 0; j < i; ++j)
  3186.                  if(sd->stc.extc[i] == sd->stc.extc[j]) break;
  3187.  
  3188.               if(i == j) gs_free(sd->stc.extc[i],sd->stc.sizc[i],sizeof(float),
  3189.                             "stc_put_params");
  3190.            }
  3191.  
  3192.            if((sd->stc.extv[i] != NULL) &&
  3193.               (sd->stc.extv[i] != oldstc.extv[i]) &&
  3194.               (sd->stc.extv[i] != defext)) {
  3195.  
  3196.               for(j = 0; j < i; ++j)
  3197.                  if(sd->stc.extv[i] == sd->stc.extv[j]) break;
  3198.  
  3199.               if(i == j) gs_free(sd->stc.extv[i],sd->stc.sizv[i],sizeof(float),
  3200.                             "stc_put_params");
  3201.            }
  3202.         }                                                    /* components */
  3203.      }              /* free newly allocated arrays */
  3204.    }                /* Allocate new arrays */
  3205.    error = error > code ? code : error;
  3206.  
  3207. /*
  3208.  * finally decide upon restore or release of old, unused data
  3209.  */
  3210.    if(error != 0) { /* Undo changes */
  3211.  
  3212.       memcpy(&sd->color_info,&oldcolor,sizeof(oldcolor));
  3213.       memcpy(&sd->stc       ,&oldstc  ,sizeof(oldstc  ));
  3214.    } else {        /* undo / release */
  3215.  
  3216.       if((oldstc.escp_init.data != NULL) &&
  3217.          (oldstc.escp_init.data != sd->stc.escp_init.data)) {
  3218.             gs_free((byte *)oldstc.escp_init.data,
  3219.                             oldstc.escp_init.size,1,"stcolor/init");
  3220.       }
  3221.  
  3222.       if((oldstc.escp_release.data != NULL) &&
  3223.          (oldstc.escp_release.data != sd->stc.escp_release.data)) {
  3224.             gs_free((byte *)oldstc.escp_release.data,
  3225.                             oldstc.escp_release.size,1,"stcolor/release");
  3226.       }
  3227.  
  3228.       if((oldstc.am != NULL) && (oldstc.am != sd->stc.am)) {
  3229.          if(     oldcolor.num_components == 1) i =  3;
  3230.          else if(oldcolor.num_components == 3) i =  9;
  3231.          else                                  i = 16;
  3232.          gs_free(oldstc.am,i,sizeof(float),"stc_put_params");
  3233.       }
  3234.  
  3235.       for(i = 0; i < 4; ++i) {
  3236.          int j;
  3237.  
  3238.          if((oldstc.extc[i] != NULL) &&
  3239.             (oldstc.extc[i] != sd->stc.extc[i]) &&
  3240.             (oldstc.dither  != NULL) &&
  3241.             (oldstc.extc[i] != defext)) {
  3242.  
  3243.             for(j = 0; j < i; ++j) if(oldstc.extc[i] == oldstc.extc[j]) break;
  3244.  
  3245.             if(i == j) gs_free(oldstc.extc[i],oldstc.sizc[i],sizeof(float),
  3246.                             "stc_put_params");
  3247.          }
  3248.  
  3249.          if((oldstc.extv[i] != NULL) &&
  3250.             (oldstc.extv[i] != sd->stc.extv[i]) &&
  3251.             (oldstc.extv[i] != defext)) {
  3252.  
  3253.             for(j = 0; j < i; ++j) if(oldstc.extv[i] == oldstc.extv[j]) break;
  3254.  
  3255.             if(i == j) gs_free(oldstc.extv[i],oldstc.sizv[i],sizeof(float),
  3256.                             "stc_put_params");
  3257.          }
  3258.       }
  3259.  
  3260. /*
  3261.  * Close the device if colormodel changed or recomputation
  3262.  * of internal arrays is required
  3263.  */
  3264.       if(sd->is_open) { /* we might need to close it */
  3265.          bool doclose = false;
  3266.          if((sd->color_info.num_components != oldcolor.num_components) ||
  3267.             (sd->color_info.depth          != oldcolor.depth         ) ||
  3268.             (sd->stc.bits                  != oldstc.bits            ) ||
  3269.             (sd->stc.dither                != oldstc.dither          ))
  3270.             doclose = true;
  3271.  
  3272.          for(i = 0; i < sd->color_info.num_components; ++i) {
  3273.             if(sd->stc.extv[i] != oldstc.extv[i]) doclose = true;
  3274.             if(sd->stc.extc[i] != oldstc.extc[i]) doclose = true;
  3275.          }
  3276.          if(doclose) {
  3277.             stc_freedata(&oldstc);
  3278.             for(i = 0; i < 4; ++i) {
  3279.                sd->stc.vals[i] = NULL;
  3280.                sd->stc.code[i] = NULL;
  3281.             }
  3282.  
  3283.             gs_closedevice(pdev);
  3284.          }
  3285.       }                 /* we might need to close it */
  3286.  
  3287.    }
  3288.  
  3289.    return error;
  3290. }
  3291. /*
  3292.  * 1Bit CMYK-Algorithm
  3293.  */
  3294.  
  3295. private int
  3296. stc_gscmyk(stcolor_device *sdev,int npixel,byte *in,byte *buf,byte *out)
  3297. {
  3298.  
  3299.    byte *ip = in;
  3300.    int   error = 0;
  3301.  
  3302.  
  3303. /* ============================================================= */
  3304.    if(npixel > 0) {  /* npixel >  0 -> scanline-processing       */
  3305. /* ============================================================= */
  3306.  
  3307.       int p;
  3308.  
  3309. /*
  3310.  *    simply split the two pixels rsiding in a byte
  3311.  */
  3312.       for(p = npixel; p > 0; --p) { /* loop over pixels */
  3313.          byte tmp =*ip++;
  3314.  
  3315.          *out++ = (tmp>>4) & 15;
  3316.          if(--p <= 0) break;
  3317.  
  3318.          *out++ =  tmp     & 15;
  3319.  
  3320.       }                                   /* loop over pixels */
  3321.  
  3322. /* ============================================================= */
  3323.    } else {          /* npixel <= 0 -> initialisation            */
  3324. /* ============================================================= */
  3325.  
  3326. /*    we didn't check for the white-calls above, so this may cause errors */
  3327.       if(sdev->stc.dither->flags & STC_WHITE)              error = -1;
  3328.  
  3329. /*    if we're not setup for bytes, this is an error too */
  3330.       if((sdev->stc.dither->flags & STC_TYPE) != STC_BYTE) error = -2;
  3331.  
  3332. /*    This IS a direct-driver, so STC_DIRECT must be set! */
  3333.       if((sdev->stc.dither->flags & STC_DIRECT) == 0)      error = -3;
  3334.  
  3335. /*    and cmyk-mode is the only supported mode */
  3336.       if(sdev->color_info.num_components != 4)             error = -4;
  3337.  
  3338. /*    and we support only 4Bit-Depth here */
  3339.       if(sdev->color_info.depth != 4)                      error = -5;
  3340.  
  3341. /* ============================================================= */
  3342.    } /* scanline-processing or initialisation */
  3343. /* ============================================================= */
  3344.  
  3345.    return error;
  3346. }
  3347.  
  3348. /*
  3349.  * The following is an algorithm under test
  3350.  */
  3351. private int
  3352. stc_hscmyk(stcolor_device *sdev,int npixel,byte *in,byte *buf,byte *out)
  3353. {
  3354.  
  3355. /* ============================================================= */
  3356.    if(npixel < 0) {  /* npixel <= 0 -> initialisation            */
  3357. /* ============================================================= */
  3358.  
  3359.       int i,i2do;
  3360.       long *lp = (long *) buf;
  3361.  
  3362. /* CMYK-only algorithm */
  3363.       if( sdev->color_info.num_components != 4)                      return -1;
  3364.  
  3365. /*
  3366.  * check wether stcdither & TYPE are correct
  3367.  */
  3368.       if(( sdev->stc.dither                    == NULL) ||
  3369.          ((sdev->stc.dither->flags & STC_TYPE) != STC_LONG))         return -2;
  3370.  
  3371. /*
  3372.  * check wether the buffer-size is sufficiently large
  3373.  */
  3374.       if(((sdev->stc.dither->flags/STC_SCAN) < 1) ||
  3375.          ( sdev->stc.dither->bufadd          <
  3376.           (1 + 2*sdev->color_info.num_components)))                  return -3;
  3377.  
  3378. /*
  3379.  * must have STC_CMYK10, STC_DIRECT, but not STC_WHITE
  3380.  */
  3381.       if((sdev->stc.dither->flags & STC_CMYK10) == 0)                return -4;
  3382.       if((sdev->stc.dither->flags & STC_DIRECT) == 0)                return -5;
  3383.       if((sdev->stc.dither->flags & STC_WHITE ) != 0)                return -6;
  3384.  
  3385. /*
  3386.  * Must have values between 0-1023.0
  3387.  */
  3388.       if((sdev->stc.dither->minmax[0] !=    0.0) ||
  3389.          (sdev->stc.dither->minmax[1] != 1023.0))                    return -7;
  3390. /*
  3391.  * initialize buffer
  3392.  */
  3393.  
  3394.      i2do            = 1 + 8 - 4 * npixel;
  3395.      lp[0] = 0;
  3396.  
  3397.       if(sdev->stc.flags & STCDFLAG0) {
  3398.         for(i = 1; i < i2do; ++i) lp[i] = 0;
  3399.       } else {
  3400.         for(i = 1; i < i2do; ++i)  lp[i] = (rand() % 381) - 190;
  3401.       }
  3402.  
  3403. /* ============================================================= */
  3404.    } else {  /* npixel > 0 && in != NULL  -> scanline-processing */
  3405. /* ============================================================= */
  3406.  
  3407.       long errc[4],*errv;
  3408.       int             step  = buf[0] ? -1 : 1;
  3409.       stc_pixel *ip    =  (stc_pixel *) in;
  3410.  
  3411.       buf[0] = ~ buf[0];
  3412.       errv   =  (long *) buf + 5;
  3413.  
  3414.       if(step < 0) {
  3415.         ip   += npixel-1;
  3416.         out  += npixel-1;
  3417.         errv += 4*(npixel-1);
  3418.       }
  3419.  
  3420.       errc[0] = 0; errc[1] = 0; errc[2] = 0; errc[3] = 0;
  3421.  
  3422.       while(npixel-- > 0) {
  3423.  
  3424.          register  stc_pixel ci,mode;
  3425.          register  long           k,v,n;
  3426.          register  int pixel; /* internal pixel-value */
  3427.  
  3428.          ci      = *ip; ip += step;
  3429.  
  3430.          mode    = ci & 3;
  3431.          k       = (ci>>2) & 0x3ff;
  3432.          pixel   = 0;
  3433.  
  3434.          v       = k+errv[3]+((7*errc[3])>>4);
  3435.  
  3436.          if(mode == 3) { /* only Black allowed to fire */
  3437.  
  3438.             if(v > 511) {
  3439.                v     -= 1023;
  3440.                pixel  = BLACK;
  3441.             }
  3442.             errv[3-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3443.             errv[3]            = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
  3444.             errc[3]            = v;
  3445.  
  3446.             errv[0] = errv[0] < -190 ? -190 : errv[0] < 190 ? errv[0] : 190;
  3447.             errv[1] = errv[1] < -190 ? -190 : errv[1] < 190 ? errv[1] : 190;
  3448.             errv[2] = errv[2] < -190 ? -190 : errv[2] < 190 ? errv[2] : 190;
  3449.  
  3450.             errc[0] = 0; errc[1] = 0; errc[2] = 0;
  3451.  
  3452.          } else if(v > 511) { /* black known to fire */
  3453.  
  3454.             v    -= 1023;
  3455.             pixel = BLACK;
  3456.  
  3457.             errv[3-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3458.             errv[3]            = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
  3459.             errc[3]            = v;
  3460.  
  3461.             n = (ci>>12) & 0x3ff;
  3462.  
  3463.             if(mode == 2) { v = k; }
  3464.             else          { v = n; n = (ci>>22) & 0x3ff; }
  3465.  
  3466.             v += errv[2]+((7*errc[2])>>4)-1023;
  3467.             if(v < -511) v = -511;
  3468.             errv[2-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3469.             errv[2]            = ((5*v+errc[2]+8)>>4);/* 5/16 +1/16 (rest) */
  3470.             errc[2]            = v;
  3471.  
  3472.             if(mode == 1) { v = k; }
  3473.             else          { v = n; n = (ci>>22) & 0x3ff; }
  3474.  
  3475.             v += errv[1]+((7*errc[1])>>4)-1023;
  3476.             if(v < -511) v = -511;
  3477.             errv[1-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3478.             errv[1]            = ((5*v+errc[1]+8)>>4);/* 5/16 +1/16 (rest) */
  3479.             errc[1]            = v;
  3480.  
  3481.             if(mode == 0) v = k;
  3482.             else          v = n;
  3483.  
  3484.             v += errv[0]+((7*errc[0])>>4)-1023;
  3485.             if(v < -511) v = -511;
  3486.             errv[0-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3487.             errv[0]            = ((5*v+errc[0]+8)>>4);/* 5/16 +1/16 (rest) */
  3488.             errc[0]            = v;
  3489.  
  3490.          } else { /* Black does not fire initially */
  3491.  
  3492.             long kv = v; /* Black computed after colors */
  3493.  
  3494.             n = (ci>>12) & 0x3ff;
  3495.  
  3496.             if(mode == 2) { v = k; }
  3497.             else          { v = n; n = (ci>>22) & 0x3ff; }
  3498.  
  3499.             v += errv[2]+((7*errc[2])>>4);
  3500.             if(v > 511) {
  3501.                pixel |= YELLOW;
  3502.                v     -= 1023;
  3503.             }
  3504.             errv[2-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3505.             errv[2]            = ((5*v+errc[2]+8)>>4);/* 5/16 +1/16 (rest) */
  3506.             errc[2]            = v;
  3507.  
  3508.             if(mode == 1) { v = k; }
  3509.             else          { v = n; n = (ci>>22) & 0x3ff; }
  3510.  
  3511.             v += errv[1]+((7*errc[1])>>4);
  3512.             if(v > 511) {
  3513.                pixel |= MAGENTA;
  3514.                v     -= 1023;
  3515.             }
  3516.             errv[1-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3517.             errv[1]            = ((5*v+errc[1]+8)>>4);/* 5/16 +1/16 (rest) */
  3518.             errc[1]            = v;
  3519.  
  3520.             if(mode == 0) v = k;
  3521.             else          v = n;
  3522.  
  3523.             v += errv[0]+((7*errc[0])>>4);
  3524.             if(v > 511) {
  3525.                pixel |= CYAN;
  3526.                v     -= 1023;
  3527.             }
  3528.             errv[0-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3529.             errv[0]            = ((5*v+errc[0]+8)>>4);/* 5/16 +1/16 (rest) */
  3530.             errc[0]            = v;
  3531.  
  3532.             v = kv;
  3533.             if(pixel == (CYAN|MAGENTA|YELLOW)) {
  3534.                pixel = BLACK;
  3535.                v     = v > 511 ? v-1023 : -511;
  3536.             }
  3537.             errv[3-(step<<2)] += ((3*v+8)>>4);        /* 3/16 */
  3538.             errv[3]            = ((5*v+errc[3]+8)>>4);/* 5/16 +1/16 (rest) */
  3539.             errc[3]            = v;
  3540.  
  3541.          }
  3542.  
  3543.          errv += step<<2;
  3544.          *out  = pixel; out += step;
  3545.  
  3546.       }                                         /* loop over pixels */
  3547.  
  3548. /* ============================================================= */
  3549.    } /* initialisation, white or scanline-processing             */
  3550. /* ============================================================= */
  3551.  
  3552.    return 0;
  3553. }
  3554.